Server/client with ESP32/Processing

Good morning,
I am currently in university, and my end-of-year project is to create an automatic greenhouse.

I therefore have to create a Human Machine Interface with Processing and a server which will group together all the sensor data.

My Human Machine Interface on processing is my client, which will display the greenhouse data but which will also allow the user to modify the greenhouse parameters.

The client must therefore receive data from the server but also send it to it.

The server is an ESP32 WROOM. I already managed to make a program where Processing is the client and sends data to the ESP32 server. But I can’t do the opposite (the ESP32 server sends data to the Processing client). I’ve done a lot of searching and can’t seem to find it.

So I come to ask you for help to help me move forward with this little blockage.

Thank you in advance for your advice.

The following programs are those that work and that I managed to do, but cannot find so that the client receives data from the server.
CODE PROCESSING CLIEN

import processing.net.*;

Client c;
String input;
int data[];

void setup() 
{
  size(450, 255);
  background(204);
  stroke(0);
  frameRate(5); // Slow it down a little
  // Connect to the server's IP address and port
  c = new Client(this, "adress IP du server", 80); // Replace with your server's IP and port
}

void draw() 
{
  if (mousePressed == true) {
    // Draw our line
    stroke(255);
    line(pmouseX, pmouseY, mouseX, mouseY);
    // Send mouse coords to other person
    c.write(pmouseX + " " + pmouseY + " " + mouseX + " " + mouseY + "\n");
    println(pmouseX + " " + pmouseY + " " + mouseX + " " + mouseY + "\n");
  }
  // Receive data from server
  if (c.available() > 0) {
    input = c.readString();
    input = input.substring(0, input.indexOf("\n")); // Only up to the newline
    data = int(split(input, ' ')); // Split values into an array
    // Draw line using received coords
    stroke(0);
    line(data[0], data[1], data[2], data[3]);
     println("reading message from client at " + c.ip() + " <- input=", input, "; data=", data);

  }
}

CODE SERVER ESP32

#include <WiFi.h>

const char* ssid     = "";
const char* password = "";

int counter;
WiFiServer server(80);



void setup()
{
    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());
    
    server.begin();


}

void loop(){
 WiFiClient client = server.available(); 

  if (client) {                             // if you get a client,
    Serial.println("New Client.");           // print a message out the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) { 
      server.write(200);// loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();// read a byte, then
        Serial.write(c);
                               // print it out the serial monitor
    }
    }
    // close the connection:
    client.stop();
    Serial.println("Client Disconnected.");
  }
}

Example sending data from esp32

1 Like

Here is another library with sending receiving examples

1 Like

Hi @Bellatore69, I’ve used ESP8266 on a few small projects, never ESP32, but I think in respect of communicating they are the same. If that’s wrong, someone please correct me.

I use UDP messages. (Processing, library manager, UDP). One of life’s challenges is going to a code club with an ESP8266 (running a fan speed control) and a Pi with an application (web-server written in js, but Processing can do the same comms) You don’t know what IP addresses the devices will get, so I make the ESP do a UDP broadcast a message each minute. The message has the source IP and contains the name of the program running in the ESP. The Pi receives broadcast messages and looks for that name. Once found, it can send frequent UDP requests to the ESP get response.

I’m away from home at the moment, without ESP and latest versions of programs, but what follows is:

ESP_Fan_Speed.ino - ESP code. If you load it and go to it’s web-page you’ll recognise it as starting from one of the given examples. +Extra buttons, +OTA, +UDP messages. You’ll have to hard code your WiFi details on line 86.

UDP_Scan.js - the relevant parts of my js server to see the recognition of ESP program name and subsequent enquiry.

ESP_Control_UDP.pde - Hard-coded ESP’s IP address on line 45. Run, click on window, press ‘A’ and it should enquire to ESP and get reply.

The part I don’t have with me is the Processing code to get the IP address from the broadcast mesage., but once you have some messages working it’s obvious.

Hope this makes sense and helps,

Richard.

ESP_Fan_Speed.ino

// Import required libraries
// For WiFi and OTA
#include <Arduino.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>
#include <WiFiUdp.h>


// For timer interrupts
#include <Ticker.h>

#define pM pinMode
#define dR digitalRead
#define aW analogWrite
#define dW digitalWrite

#define rcv_pkt_size 100  // examples had another value, WMini crashed with that

const boolean TT = true;
const boolean FF = false;


float DTTemp0;
float DTTemp1;


// Network credentials
const char* ssid1 = "X"; const char* password1 = "xxx";
const char* ssid0 = "Y"; const char* password0 = "yyy";


WiFiUDP Udp;
unsigned int localUdpPort = 4210;  // local port to listen on
char incomingPacket[255];  // buffer for incoming packets
char  replyPacket[] = "Hi there! received your message :-)";  // a reply string to send back


int secs = 0;   // 0..59
int mins = 0;   // 0..59
int hors = 0;   // 0..23
int days = 0;

bool ledState = 0;

const int fanOn__Pin = D5;   // fan on-off
const int fanSL__Pin = D6;
const int fanPV__Pin = D4;   // Pulse input
const int ledRd1_Pin = D1;   // Red Led - separate (green broken)
const int ledGr__Pin = D2;   // Green LED - red/green
const int ledRd2_Pin = D3;   // Red   LED - red/green

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <title>ESP Fan Speed Control</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,">
  <style>
  html {font-family: Arial, Helvetica, sans-serif;text-align: left;}
  h1 {font-size: 1.8rem; color: white;}
  h2{font-size: 1.5rem; font-weight: bold; color: #143642;}
  .topnav {overflow: hidden; background-color: #143642;}
  body {margin: 0;}
  .content {padding: 30px; max-width: 600px; margin: 0 auto;}
  .card {
    background-color: #F8F7F9;;
    box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
    padding-top:10px;
    padding-bottom:20px;
  }
  .button {
    padding: 12px 12px;
    font-size: 24px;
    text-align: center;
    outline: none;
    color: #fff;
    background-color: #0f8b8d;
    border: none;
    border-radius: 5px;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    -webkit-tap-highlight-color: rgba(0,0,0,0);
   }
   /*.button:hover {background-color: #0f8b8d}*/
   .button:active { 
     background-color: #0f8b8d;
     box-shadow: 2 2px #CDCDCD;
     transform: translateY(2px);
   }
   .state {
     padding-right: 35px;
     font-size: 2.0rem;
     color:#4c4c4c;
     font-weight: bold;
   }
   .r1 {
      margin: 0;
      padding-top: 0px;
      padding-bottom: 0px;
      font-size: 1.5rem;
      color:#50D010;
  }
  </style>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
</head>
<body>
  <div class="topnav">
    <h1>ESP8266 Fan Speed Control</h1>
  </div>
  <div class="content">
    <div class="card">
      <p><button id="button" class="button">Toggle Red LED.</button> <span id="stat1" class="state">%STATE%</span></p>
      <p><button id="buttn2" class="button">Fan Off</button>
         <button id="buttn3" class="button">Fan On</button> 
         <span id="FN" class="state">%FanOn%</span></p>
         
         <p>   
         <button id="ButFS1" class="button">Fan Speed 1</button> 
         <button id="ButFS2" class="button">2</button> 
         <button id="ButFS3" class="button">3</button> 
         <button id="ButFS4" class="button">4</button> 
         <button id="ButFS5" class="button">5</button>
         <span id="FSL"      class="state">%FanSL%</span>
         <span id="FSPV"     class="state">%FanPV%</span>rev/min
         </p> 
         
      <p class="r1"><span>ESP Count:  </span> <span id="EC">EC</span></p>

      <p>More info and source code at:</p>
      <p>sites.google.com/view/processing-and-arduino-notes.</p>
      <p>That's a reference, but not a link, because the link made an error.</p>
      <p>You need internet, not ESP WiFi.</p>
      <p>On that page, near the end, see 'ESP8266 Fan Control'.</p>
      <br>
      <p>%file%</p>

      
    </div>
  </div>
<script>
  var gateway = `ws://${window.location.hostname}/ws`;
  var websocket;
  window.addEventListener('load', onLoad);
  
  function initWebSocket() {
    console.log('G ' + gateway);
    console.log('Trying to open a WebSocket connection...');
    websocket = new WebSocket(gateway);
    websocket.onopen    = onOpen;
    websocket.onclose   = onClose;
    websocket.onmessage = onMessage; // <-- add this line
  }
  function onOpen(event)  {console.log('Connection opened');}
  function onClose(event) {console.log('Connection closed'); setTimeout(initWebSocket, 2000);}
  
  function onMessage(event) {
    
    var state;
    var ary;
    var id;
    var colour;
    
    //console.log(event.data);
    
    if (event.data == "1") {state = "ON" ; 
        document.getElementById('stat1').innerHTML = state;
    } 
    if (event.data == "0") {state = "OFF"; 
      document.getElementById('stat1').innerHTML = state;
    }

    ary = event.data.split(",");
    id = 'EC';   if (ary[0] == id) {document.getElementById(id).innerHTML = ary[1];}
    id = 'T0';   if (ary[0] == id) {document.getElementById(id).innerHTML = ary[1];}
    id = 'T1';   if (ary[0] == id) {document.getElementById(id).innerHTML = ary[1];}    
    id = 'FN';   if (ary[0] == id) {document.getElementById(id).innerHTML = ary[1];}    
    id = 'FSL';  if (ary[0] == id) {document.getElementById(id).innerHTML = ary[1];}
    id = 'FSPV'; if (ary[0] == id) {document.getElementById(id).innerHTML = ary[1];}
  }
  
  function onLoad(event) {
    initWebSocket();
    initButton();
  }
  
  function initButton() {
    document.getElementById('button').addEventListener('click', toggle);
    document.getElementById('buttn3').addEventListener('click', On_);
    document.getElementById('buttn2').addEventListener('click', Off);

    document.getElementById('ButFS1').addEventListener('click', ButFS1);
    document.getElementById('ButFS2').addEventListener('click', ButFS2);
    document.getElementById('ButFS3').addEventListener('click', ButFS3);
    document.getElementById('ButFS4').addEventListener('click', ButFS4);
    document.getElementById('ButFS5').addEventListener('click', ButFS5);      
  }
  function toggle(){websocket.send('toggle');}
  function On_(){websocket.send('On_');}
  function Off(){websocket.send('Off');}

  function ButFS1(){websocket.send('FS1');}
  function ButFS2(){websocket.send('FS2');}
  function ButFS3(){websocket.send('FS3');}
  function ButFS4(){websocket.send('FS4');}
  function ButFS5(){websocket.send('FS5');}
  
</script>
</body>
</html>)rawliteral";

// these relic for smaller fan on other project?
int fanSenseState0 = 0;
int fanSenseState1 = 0;   // 0 = normal, 1 = stuck

Ticker blinker;
// SWiF2-80P Fan (Yellow)
int fanOn = 0;  // User on/off
int fan_state;  // 0/1 as fan goes round
int led_state;
int fan_SL;
int fan_count;
int fan_speed;

ICACHE_RAM_ATTR void fan_ISR() {
  // 2 per rev
  fan_state = (~fan_state) & 1;
  dW(ledGr__Pin, fan_state);
  //if (fan_state) {fan_count++;}  // 1 per rev
  fan_count++;
}

ICACHE_RAM_ATTR void timer_ISR() {
  // each 2 seconds
  led_state = (~led_state) & 1;
  //dW(ledRd1_Pin, led_state);
  fan_speed = fan_count * 15;
  Serial.print("Fan Count: ");
  Serial.print(fan_count);
  Serial.print(" /2Sec ");  // half revs per 2 sec.
  Serial.print(fan_speed);
  Serial.print(" R/min");
  Serial.println();
  ws.textAll("FSPV," + String(fan_speed)); // R/Min
  fan_count = 0;
}


void notifyClients() {
  ws.textAll(String(ledState));
}

void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
  AwsFrameInfo *info = (AwsFrameInfo*)arg;
  if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
    data[len] = 0;
    if (strcmp((char*)data, "toggle") == 0) {
      ledState = !ledState;
      notifyClients();
    }
    if (strcmp((char*)data, "Off") == 0) {
      fanOn = 0;
      dW(fanOn__Pin, 0);
      ws.textAll("FN,0");
    }
    if (strcmp((char*)data, "On_") == 0) {
      fanOn = 1;
      dW(fanOn__Pin, 1);
      ws.textAll("FN,1");
    }


    if (strcmp((char*)data, "FS1") == 0) {
      aW(fanSL__Pin, 1);
      fan_SL = 1;
      ws.textAll("FSL,1");
    }
    if (strcmp((char*)data, "FS2") == 0) {
      aW(fanSL__Pin, 430);
      fan_SL = 2;
      ws.textAll("FSL,2");
    }
    if (strcmp((char*)data, "FS3") == 0) {
      aW(fanSL__Pin, 590);
      fan_SL = 3;
      ws.textAll("FSL,3");
    }
    if (strcmp((char*)data, "FS4") == 0) {
      aW(fanSL__Pin, 680);
      fan_SL = 4;
      ws.textAll("FSL,4");
    }
    if (strcmp((char*)data, "FS5") == 0) {
      aW(fanSL__Pin, 1023);
      fan_SL = 5;
      ws.textAll("FSL,5");
    }
  }
}

void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type,
             void *arg, uint8_t *data, size_t len) {
  switch (type) {
    case WS_EVT_CONNECT:
      Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
      break;
    case WS_EVT_DISCONNECT:
      Serial.printf("WebSocket client #%u disconnected\n", client->id());
      break;
    case WS_EVT_DATA:
      handleWebSocketMessage(arg, data, len);
      break;
    case WS_EVT_PONG:
    case WS_EVT_ERROR:
      break;
  }
}

void initWebSocket()
{
  ws.onEvent(onEvent);
  server.addHandler(&ws);
}

String processor(const String& var)
{
  Serial.println(var);
  if (var == "STATE")
  {
    if (ledState) {
      return "ON" ;
    }
    else         {
      return "OFF";
    }
  }
  if (var == "FanOn") {
    return String(fanOn);
  }
  if (var == "FanPV") {
    return String(fan_speed);
  }
  if (var == "FanSL") {
    return String(fan_SL);
  }

  if (var == "file") return String(__FILE__    __DATE__    __TIME__);
  
  return String();
}

void set_udp_msg(char msg[]) {
  // going to assume the msg we've been given is long enough
  char fMsg[80];
  int ix;

  sprintf(fMsg, "%s", __FILE__);
  ix = 0;
  while (1) {
    if (fMsg[ix] == '.') {
      fMsg[ix] = 0; break;
    }
    ix++;
  }
  sprintf(msg, "%s,%d,%d,%d,%d,%d,%d", fMsg, hors, mins, secs, fanOn, fan_SL, fan_speed);
}

void UDP_Brd() {
  // UDP Broadcast
  char msg[120]; // crude guess at length

  IPAddress ipa(0, 0, 0, 0);

  ipa[0] = WiFi.localIP()[0];
  ipa[1] = WiFi.localIP()[1];
  ipa[2] = WiFi.localIP()[2];
  ipa[3] = 255;

  set_udp_msg(msg);
  Udp.beginPacket(ipa, 8123); // Port??
  Udp.write(msg);
  Udp.endPacket();
}

int udpCount  = 0;  // count udp receive


void doUDP() {
  // If there's any UDP message, receive and send response

  char packetBuffer[rcv_pkt_size];
  char msg[10 * 12]; // crude assume bytes * values
  char cmdCh;

  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    udpCount++;
    IPAddress remote = Udp.remoteIP();

    // Print...
    Serial.print(" Rcv size: ");
    Serial.print(packetSize);
    Serial.print("From: ");
    for (int i = 0; i < 4; i++)
    {
      Serial.print(remote[i], DEC);
      if (i < 3) {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.print(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer, rcv_pkt_size);
    Serial.print("Contents: ~");
    Serial.print(packetBuffer);
    Serial.print("~");
    cmdCh = packetBuffer[0];

    if (cmdCh == 'A') {
      // send a reply, to the IP address and port that sent us the packet we received
      set_udp_msg(msg);
      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
      Udp.write(msg);
      Udp.endPacket();
    }
  }
}

void print_addr()
{
  // Print the IP address to serial
  Serial.printf("Listening on IP %s, UDP port %d. ", WiFi.localIP().toString().c_str(), localUdpPort);
  Serial.println();
}


// State values.
int actCont;    // counter controlling request and read of BME280

/*

  We don't know if int is 16 or 31 bit.  Board dependent.

  unsigned 16 bit max is 65535
  if seconds then         1092 minutes
                          18 hours

  millis() is unsiged long, overflow is 50 days

*/




void setup() {
  bool status;
  int tries;
  delay(2000);
  Serial.begin(9600);
  delay(500);

  pM(fanOn__Pin , OUTPUT);
  pM(fanSL__Pin , OUTPUT);

  pM(ledRd1_Pin , OUTPUT);
  pM(ledGr__Pin , OUTPUT);
  pM(ledRd2_Pin , OUTPUT);

  pM(fanPV__Pin , INPUT_PULLUP);

  WiFi.mode(WIFI_AP_STA);

  // Connect to Wi-Fi - try 2 nets in turn
  if (WiFi.status() != WL_CONNECTED) {
    WiFi.begin(ssid0, password0, 10);
    tries = 0;
    while (WiFi.status() != WL_CONNECTED)
    {
      delay(1000);
      Serial.print("Connecting to WiFi...~");
      Serial.print(" ");
      Serial.print(ssid0);
      Serial.print(" ");
      Serial.print(tries);
      Serial.println();
      tries++;
      if (tries > 5) {
        break;
      }
    }
  }

  if (WiFi.status() != WL_CONNECTED) {
    WiFi.begin(ssid1, password1);
    tries = 0;
    while (WiFi.status() != WL_CONNECTED)
    {
      delay(1000);
      Serial.print("Connecting to WiFi...");
      Serial.print(" ");
      Serial.print(ssid1);
      Serial.print(" ");
      Serial.print(tries);
      Serial.println();
      tries++;
      if (tries > 5) {
        break;
      }
    }
  }

  // Print ESP Local IP Address
  Serial.println(WiFi.localIP());

  initWebSocket();

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/html", index_html, processor);
  });

  // Start ElegantOTA
  AsyncElegantOTA.begin(&server);
  // Start server
  server.begin();

  Udp.begin(localUdpPort);

  // Set the interrupt for fan and timer
  blinker.attach_ms(2000, timer_ISR);
  //attachInterrupt(digitalPinToInterrupt(D4), fan_ISR, RISING);
  attachInterrupt(D4, fan_ISR, RISING);

  delay(4000);  // what for?
}


long lopCount = 0;

int sec0 = 0;
int sec1;

int sw1Stat0 = -2;
int sw1Stat1;
int sw2Stat0 = -2;
int sw2Stat1;

int serCount;

void loop()
{
  int port_ix;
  int new_in;
  int in_val_ix;
  char timeMsg[50];
  char uMsg[50];
  char fMsg[50];
  int ix;


  // Calculate dd hh:mm:ss
  sec1 = millis() / 1000;
  if (sec1 != sec0) {
    secs++;
    if (secs >= 60) {
      mins++;
      if (mins >= 60) {
        hors++;
        if (hors >= 24) {
          days++;
          hors = 0;
        }
        mins = 0;
      }
      secs = 0;
    }
    sec0 = sec1;
  }
  sprintf(timeMsg, "%02d:%02d:%02d", hors, mins, secs);

  if (lopCount % 100 == 0)
  {
    // each second...
    if (actCont % 2 == 0) {
      ws.textAll("EC," + String(actCont));
      ws.textAll("T0," + String(actCont % 57));
      ws.textAll("T1," + String(actCont % 31));
    }

    if (actCont % 20 == 0)
    {
      Serial.printf("%s %s %s\n", __FILE__, __DATE__, __TIME__);
      print_addr();
    }
    if (actCont % 15 == 0) {
      UDP_Brd();
    }
    actCont++;
  }


  if (lopCount % 100 == 0 && actCont % 2 == 0)
  {
    Serial.print(lopCount);
    Serial.print(" ");
    if (actCont % (2 * 3) == 2 * 3 - 1) {
      Serial.println();
    }

    if (actCont % (2 * 30) == 0)
    {
      Serial.println();
      Serial.print(__FILE__);
      Serial.print(" ");
      Serial.print(__DATE__);
      Serial.print(" ");
      Serial.print(__TIME__);
      Serial.println();
    }
  }


  if (lopCount % 20 == 0)
  {
    // copy the web-driven state to the led
    dW(ledRd1_Pin, ledState);
    ws.cleanupClients();
  }

  if (lopCount % 10 == 0) {
    // Any udp action required?
    doUDP();
  }

  //fanSenseState1 = dR(SpedPin);
  if (fanSenseState1 != fanSenseState0) {
    ws.textAll("F1," + String(fanSenseState1));
    serCount++;
    if (serCount > 80) {
      serCount = 0;
      Serial.println();
    }
    fanSenseState0 = fanSenseState1;
  }

  int period = 600;
  if (lopCount % (period / 2) == 0) {
  }

  // Copy speed pulse sense pin to led.
  //dW(ledGr__Pin, dR(fanPV__Pin));

  lopCount++;
  delay(10);
}

UDP_Scan.js


// This is not a working program.  It's an extract of
// the code lines that exchanges UDP messages with the 
// ESP8255 running Fan_Speed_Control.

const dgram = require('dgram');
const srvr_udp = dgram.createSocket('udp4');


var iESPTimeout = 0;


var ESP_IPAddr;
var ESP_Port;

srvr_udp.bind(8123);


srvr_udp.on('message', (msg, rinfo) => {
  var ix;
  var sMsg;
  var vals;
  var len1;

  len1 = msg.length;
  if (1)
  {
    console.log(procs.getDateTime(1)
      + ` Rcv: from ${rinfo.address}:${rinfo.port} ${msg}`);
  }
  sMsg = msg.toString();
  //console.log(sMsg);
  vals = sMsg.split(',');
  if (vals[0] == "ESP_Fan_Speed") {
    if (iESPTimeout == 0) {
       // Store the address to send request
       ESP_IPAddr = rinfo.address;
       ESP_Port   = rinfo.port
    }
    //console.log("Fan speed: " + vals[5] + ' rpm.') ;

    FanOn    = vals[4];
    FanSet   = vals[5];
    FanSpeed = vals[6];

    iESPTimeout = 20;
  }
});


function udp_req() {  // Send request to ESP for data.
  var msg;
  msg = 'A';
  srvr_udp.send(msg, 0, msg.length, ESP_Port, ESP_IPAddr, function (err, bytes) {});
}


 if (iUpTime % 2 == 0 && iESPTimeout) {udp_req();}

ESP_Control_UDP.pde

/**
 * (./) udp.pde - how to use UDP library as unicast connection
 * (cc) 2006, Cousot stephane for The Atelier Hypermedia
 * (->) http://hypermedia.loeil.org/processing/
 *
 * Create a communication between Processing<->Pure Data @ http://puredata.info/
 * This program also requires to run a small program on Pd to exchange data  
 * (hum!!! for a complete experimentation), you can find the related Pd patch
 * at http://hypermedia.loeil.org/processing/udp.pd
 * 
 * -- note that all Pd input/output messages are completed with the characters 
 * ";\n". Don't refer to this notation for a normal use. --
 
03/02/2021 22:24:46
- trying to get this to talk ESP8266 but it's not receiving owt.
- think that it's ESP's problem.
- Have to get something else to prove it.
 
06/02/2021 20:11:34
- this is working, but talking to ESP_UDP_Server. 
- we have 10 simulated values, sent each time we request, and plotting on GUI. 
 
 */

// import UDP library



import hypermedia.net.*;

final boolean T = true;
final boolean F = false;

UDP udp;  // define the UDP object

int iDisplayIx = 0;
int iDisplayLines = 20;
boolean bNewData = F; 
String sRcvMsg;


void send_msg()
{
  String message  = str( key );      // the message to send
  String ip       = "192.168.1.8";   // the remote IP address
  int port        = 4210;            // the destination port
  
  // formats the message for Pd
  //message = message + ";"; //\n";    
  //print(frameCount); print(" Send ");
  //send the message
  udp.send(message, ip, port);    
}

long count;
void setup() 
{
  size(1100, 500);
  frameRate(20);
  // create a new datagram connection on port 6000
  // and wait for incomming message
  udp = new UDP( this, 8889 );
  //udp.log( true ); 		// <-- printout the connection activity
  udp.listen( true );

  background(0);
  count = 0;
}

//process events
void draw() 
{
  int iValues[];
  int data_ix;
  
  if (count % 20 == 0)
  {
    send_msg();
  }
  
  if (bNewData)
  {
    //print(iDisplayIx); print(" " );
    if (iDisplayIx == 0)
    {
      //background(0);
      fill(0);
      stroke(0);
      rect(0, 0, 460, 420);
    }
    fill(255, 255, 0);
    textSize(20);
    text(sRcvMsg, 10, 30 + iDisplayIx * 20);
    iDisplayIx++;
    iDisplayIx %= iDisplayLines;
    
    iValues = int(split(sRcvMsg, ","));
    //printArray(iValues);
    //println();
    bNewData = F;
    
    
    stroke(10);
    line(500 + (frameCount / 20) % 600, height - 10, 500 + (frameCount / 20) % 600, height - 10 - 1000 * 4 / 10); 
    pushStyle();
    colorMode(HSB);
    //stroke(255, 255, 0);
    for (data_ix = 0; data_ix < iValues.length - 1; data_ix++ )
    {
      stroke((data_ix + 1) * 255 / iValues.length, 255, 255);
      point(500 + (frameCount / 20) % 600, height - 10 - iValues[data_ix] * 4 / 10);
    }
    popStyle();
    
  }
 
  count++;
}

/** 
 * on key pressed event:
 * send the current key value over the network
 */
void keyPressed() 
{
  send_msg();
}

/**
 * To perform any action on datagram reception, you need to implement this 
 * handler in your code. This method will be automatically called by the UDP 
 * object each time he receive a nonnull message.
 * By default, this method have just one argument (the received message as 
 * byte[] array), but in addition, two arguments (representing in order the 
 * sender IP address and his port) can be set like below.
 */
// void receive( byte[] data ) { 			// <-- default handler
void receive( byte[] data, String ip, int port ) // <-- extended handler
{
  
  // get the "real" message =
  // forget the ";\n" at the end <-- !!! only for a communication with Pd !!!
  //data = subset(data, 0, data.length-2);
  sRcvMsg = new String(data);
  
  // print the result
  println( "receive: \""+sRcvMsg+"\" from "+ip+" on port "+port );
  bNewData = T; 
}

1 Like

As others commented, there are different ways to do this. If you are going for http server, perhaps you want to make GET or POST API so that the client (Processing) makes an API call (optionally send data) and the server (ESP32) returns the data.

(I couldn’t find an example for Processing + ESP32)

However, as Richard wrote, using UDP is another direction and this may be easier to understand the data flow. Since you are making a greenhouse, I assume that you don’t have to send data every 10 milliseconds, so either HTTP or UDP would be fine in your use case. My recommendation is, if you don’t have much time, UDP would give a quicker solution, and if you want to invest time and make the system efficient and scalable, HTTP would suit you better.

1 Like