Daten per WLAN verschicken und auf dem PC verarbeiten können

Hallo allerseits :wave:

ich bitte um fachlichen Rat.

Ich möchte von meinem Arduino per WLAN Daten an meinen Computer schicken und diese in einem Programm verarbeiten können.

Unten habe ich schon mal das reingestellt was das Arduino Board macht.
Kurzfassung: Es schickt jede Sekunde ein Zahl per HTML an den Client der Verbunden ist.

Nun möchte ich aber nicht den Browser öffnen um an diese "Daten" ranzukommen, sondern ein ausführbares Programm (Sprache C ) auf dem Desktop liegen, welches diese Zahl lesen, als Variable speichern und verarbeiten kann.

Ich hoffe, dass Ihr mir helfen könnt.

Gruß Tim

#include <WiFiNINA.h>

const char* ssid     = "Arduino-Access-Point";
const char* password = "12345678";

WiFiServer server(80);
WiFiClient client;

int number = 0;
String header; 

void setup() {
  Serial.begin(9600);

  Serial.print("Setting Access Point…");
  WiFi.beginAP(ssid, password);

  IPAddress IP = WiFi.localIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);  
  
  server.begin();
}

void sendData(){
 
  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // 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
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();            
            
            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\"></head>");
                        
            client.print("<p>"); client.print(number); client.println("</p>");            
            client.println("</body></html>");

            client.println();
            break;
          } 
          else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } 
        else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }

    header = "";
    
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

void loop(){
  if (!client){
    client = server.available();
  }// Listen for incoming clients
  number ++;
  sendData();
  Serial.println(number);
  delay(1000);
  
} 

Was funktionieren sollte, diese Daten per UDP an den PC senden.
Dein eigenes Programm sollte dann in der Lage sein, diese Daten zu empfangen.

Also anstelle von HTML, UDP nutzen?

und wie erkläre ich dem Programm auf dem Desktop, dass es die Daten aufsammeln soll?

Das must du deinem Programm beibringen.
Da bist du doch der Spezialist. Ich kann die sagen, wie die per WLan versendet werden.

Indem Du einen UDP-Server in der Sprache Deiner Wahl programmierst.
Zum Testen kannst Du auch erst mal den Packet Sender benutzen (der auch empfangen kann).

Gruß Tommy

Herzlichen Dank, werde ich ausprobieren.

gruß Tim

HTML ist eine Seitenbeschreibungssprache.
UDP ist ein Netzwerkprotokoll.

Die beiden KANN man gar nicht vergleichen.

Um HTML zu versenden wird meistens HTTP verwendet.
Welches dann ein Protokoll ist.
Dieses HTTP nutzt TCP/IP.
Ein Protokoll auf noch tieferer Schicht!

Lesetipp: "OSI Schichtenmodell"

Eine sehr pragmatische wenn auch nicht elegante Methode wäre

per WLAN mit UDP oder TCP die Daten an den PC zu senden
auf dem PC läuft ein Python-Script das die Daten empfängt und in eine Textdatei schreibt.
Dann kann das Weiterverarbeitungsprogramm nachschauen ob eine Textdatei vorhanden ist und die Textdatei zum weitervearbeiten einlesen.

Für UDP habe ich sowas programmiert. Das Python-Script erstellt aus dem Header der gesendeten UDP-Daten den Dateinamen. Damit kann man ganz einfach über unterschiedliche Header die Daten in verschiedenen Dateien speichern.

Der ESP32-code benutzt die lokale fritz.box als NTP-Zeitserver
Der Code erstellt auch gleich noch einen Zeitstempel der in die Daten eingefügt wird.

// I wrote some basic documentation at the end of the file
#include <WiFi.h>
#include <SafeString.h>

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

IPAddress    remoteIP     (192, 168, 178, 160); // receiver-IP
unsigned int remotePort = 4210;                 // receiver port to listen on must match the portnumber the receiver is listening to

WiFiUDP Udp;

const char* ntpServer = "fritz.box";
const long  gmtOffset_sec = 0;
const int   daylightOffset_sec = 7200;

#include <time.h>                   // time() ctime()
time_t now;                         // this is the epoch
tm myTimeInfo;                      // the structure tm holds time information in a more convient way


boolean TimePeriodIsOver (unsigned long &expireTime, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - expireTime >= TimePeriod )
  {
    expireTime = currentMillis; // set new expireTime
    return true;                // more time than TimePeriod) has elapsed since last time if-condition was true
  }
  else return false;            // not expired
}

const byte OnBoard_LED = 2;
int BlinkTime = 500;

void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);

  if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
    digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
  }
}

unsigned long TestTimer;
unsigned long UDP_SendTimer;

int myCounter = 0;
int HeaderNr  = 0;
#define MaxMsgLength 1024
createSafeString(UDP_Msg_SS, MaxMsgLength);

#define MaxHeaderLength 64
createSafeString(Header_SS, MaxHeaderLength);

#define MaxTimeStampLength 32
createSafeString(TimeStamp_SS, MaxHeaderLength);


char HeaderDelimiter = '$'; // must match the delimiter defined in the python-code

void PrintFileNameDateTime() {
  Serial.print("Code running comes from file ");
  Serial.println(__FILE__);
  Serial.print(" compiled ");
  Serial.print(__DATE__);
  Serial.println(__TIME__);
}

void showTime() {
  time(&now);                       // read the current time
  localtime_r(&now, &myTimeInfo);           // update the structure tm with the current time
  Serial.print("year:");
  Serial.print(myTimeInfo.tm_year + 1900);  // years since 1900
  Serial.print("\tmonth:");
  Serial.print(myTimeInfo.tm_mon + 1);      // January = 0 (!)
  Serial.print("\tday:");
  Serial.print(myTimeInfo.tm_mday);         // day of month
  Serial.print("\thour:");
  Serial.print(myTimeInfo.tm_hour);         // hours since midnight  0-23
  Serial.print("\tmin:");
  Serial.print(myTimeInfo.tm_min);          // minutes after the hour  0-59
  Serial.print("\tsec:");
  Serial.print(myTimeInfo.tm_sec);          // seconds after the minute  0-61*
  Serial.print("\twday");
  Serial.print(myTimeInfo.tm_wday);         // days since Sunday 0-6
  if (myTimeInfo.tm_isdst == 1)             // Daylight Saving Time flag
    Serial.print("\tDST");
  else
    Serial.print("\tstandard");

  Serial.println();
}

// my personal naming-convention parameter of functions start with prefix "p_"
void StoreTimeStampIntoSS(SafeString& p_RefToSS) {

  time(&now);                               // read the current time
  localtime_r(&now, &myTimeInfo);           // update the structure tm with the current time

  //p_RefToSS = " ";
  p_RefToSS  = myTimeInfo.tm_year + 1900;
  p_RefToSS += ".";
  if (myTimeInfo.tm_mon < 10) {
    p_RefToSS += "0"; // leading zero
  }
  p_RefToSS += myTimeInfo.tm_mon + 1;
  p_RefToSS += ".";

  
  if (myTimeInfo.tm_mday < 10) {
    p_RefToSS += "0"; // leading zero
  }
  p_RefToSS += myTimeInfo.tm_mday;

  p_RefToSS += "; ";

  if (myTimeInfo.tm_hour < 10) {
    p_RefToSS += "0"; // leading zero
  }  
  p_RefToSS += myTimeInfo.tm_hour;
  p_RefToSS += ":";

  if (myTimeInfo.tm_min < 10) {
    p_RefToSS += "0"; // leading zero
  }  
  p_RefToSS += myTimeInfo.tm_min;
  p_RefToSS += ":";

  
  if (myTimeInfo.tm_sec < 10) {
    p_RefToSS += "0"; // leading zero
  }  
  p_RefToSS += myTimeInfo.tm_sec;
  p_RefToSS += " ; ";
}


void connectToWifi() {
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    BlinkHeartBeatLED(OnBoard_LED, 333);
    delay(332);
    Serial.print(".");
  }
  Serial.print("\n connected.");
  Serial.println(WiFi.localIP() );

}

void synchroniseWith_NTP_Time() {
  Serial.print("configTime uses ntpServer ");
  Serial.println(ntpServer);
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  Serial.print("synchronising time");

  while (myTimeInfo.tm_year + 1900 < 2000 ) {
    time(&now);                       // read the current time
    localtime_r(&now, &myTimeInfo);
    BlinkHeartBeatLED(OnBoard_LED, 100);
    delay(100);
    Serial.print(".");
  }
  Serial.print("\n time synchronsized \n");
  showTime();
}

void setup() {
  Serial.begin(115200);
  Serial.println("\n Setup-Start \n");
  PrintFileNameDateTime();
  connectToWifi();
  synchroniseWith_NTP_Time();
  Header_SS = "myDemoHeader";
}

void PrintMsg() {
  Serial.print("UDP_Msg_SS #");
  Serial.print(UDP_Msg_SS);
  Serial.println("#");
}

void loop() {
  BlinkHeartBeatLED(OnBoard_LED, BlinkTime);

  if (TimePeriodIsOver(UDP_SendTimer, 2000) ) {
    Serial.print("Send Message to #");
    Serial.print(remoteIP);
    Serial.print(":");
    Serial.println(remotePort);

    UDP_Msg_SS = Header_SS;
    UDP_Msg_SS += HeaderDelimiter;
    StoreTimeStampIntoSS(TimeStamp_SS);
    UDP_Msg_SS += TimeStamp_SS;
    UDP_Msg_SS += "myUserData; ";

    UDP_Msg_SS += myCounter++;

    Serial.print("Send UDP_Msg #");
    Serial.print(UDP_Msg_SS);
    Serial.println("#");

    Udp.beginPacket(remoteIP, remotePort);
    Udp.write((const uint8_t*)UDP_Msg_SS.c_str(), UDP_Msg_SS.length() );
    Udp.endPacket();
  }
}

/*

  This is a democode that demonstrates how to send TCP/UDP-messages with a timestamp
  The time is synchronized using a NTP-server. Most local routers like Fritz!Box can be used as the NTP-timer-server

  The message has a userdefinable header which could be used for identifying the sender on the recieverside
  There is a user-definable Header-delimiter that can be used to identify which characters of the
  UDP-message belong to the header and which to the userdata

  The code makes use of the SafeString-library. PStrings don't cause memory-problems like datatype "Strings"
  and are easier to use than arrays of char. Example adding an integer to a PString-variable is as easy as
  MyPString = myInteger;

  The userdata has commas between each data so you can import the textfile
  into table-calculation-software or databases as CSV-file comma separated values

  the code has some additional useful functions as there are
  - PrintFileNameDateTime() printing the path and filename of sourcecode file this program was generated with

  - boolean TimePeriodIsOver  a non-blocking timing-function based on millis which is suitable for
  timed execution in a regular manner (repeat every n milliseconds)

  - BlinkHeartBeatLED() blinks the onboard-LED of ESP32 nodeMCU-boards. Gives visual feedback if the code is running

  The lines of code are grouped by functionality into several functions
  The functions name says what the function does

  I use this code for easy datalogging on a computer with a python-code that acts as the UDP-listener for
  incoming messages. Inside your ESP32-code you have to adjust the IP-adress to the receiver
  and the portnumber must be the same on sender (ESP32) and receiver-side

  In the python-code The header is used to create a file with the header as filename and extension ".txt" or if file
  is already existant to append the actual received UDP-message at the end of the file.

  here is the python-code that does this. I tested it with python 3.9.2 for windows
  #Start of python-code
  # very simple and short upd-receiver based on python-code I found here
  # https://www.studytonight.com/network-programming-in-python/working-with-udp-sockets#

  import socket

  sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)      # For UDP

  udp_host = socket.gethostname()            # Host IP
  udp_port = 4210                     # specified port to connect

  sock.bind((udp_host,udp_port))
  print ("Waiting for client...")

  HeaderDelimitChar = "$"

  while True:
  data,addr = sock.recvfrom(1024)         #receive data from client
  print("data #",data,"#")
  Msg = data.decode('utf-8')
  print ("Received Message: #",Msg,"# from",addr)
  EndOfHeader = Msg.find(HeaderDelimitChar)
  HeaderBytes = Msg[0:EndOfHeader]
  FileName = HeaderBytes + ".txt"
  print("Filename #",FileName,"#")
  myFile = open(FileName, "a+")
  EndOfStr = data.find(0)
  MsgToWrite = Msg[EndOfHeader + 1 :1024] + '\r'
  myFile.write(MsgToWrite);
  myFile.close()
  print ("Data #",MsgToWrite,"#")

  #End of python-code

  For learning more about python just google with keyword "python" "your keyword of interest"
*/

vgs

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.