Hallo,
ich würde gerne den ESP32 als Datenlogger verwenden.
Immer wenn einer der GPOIS von High auf Low wechselt oder andersrum, soll dies mit Zeitstempel gespeichert werden. Die Daten sollen dann in einer Datei auf einem Netzwerklaufwerk gespeichert werden, um damit anschließend eine Datenbank zu füttern.
Auf den ersten Blick gibt es im Netz viele Tutorials, wo das Problem, Werte in eine Datenbank zu schreiben, anschaulich gelöst wurde.
Betrachtet man die Lösungen allerdings näher, ist IT-Infrastruktur in Form von Domain, Webspace, Raspi als Webserver usw. erforderlich. Das steht einer Umsetzung zu Testzwecken im Wege.
Auf der anderen Seite ist es anscheinend ohne Probleme möglich, die Daten in Echtzeit auf eine vom ESP32 erstellte Internetseite sogar grafisch darzustellen; da muss es doch für mein Vorhaben, die Daten einfach lokal abzulegen, ebenfalls eine Simple Lösung geben.
Schonmal Danke für eure Tipps und Anregungen
Einmal willst Du in einer Datei auf einem Netzlaufwerk speichern (dann kannst Du auch gleich eine DB auf Deinem PC nehmen) und dann wieder lokal (also auf dem ESP).
Was denn nun? Das Verfehren ist grundlegend unterschiedlich.
Gruß Tommy
sry, meinte mit lokal "nicht im Internet".
File auf "Netzlaufwerk" als Loggerfile, also nicht auf dem ESP ist mir nicht bekannt, wie man das machen muss.
Was hindert Dich zum Entwickeln einen XAMPP auf Deinem PC zu installieren? Da hast Du Webserver, Datenbank und einiges Andere. Aufwand Downloadzeit + 3 Minuten.
Gruß Tommy
- Du kannst eine Datei im Dateisystem des ESP32 anlegen, das wäre ohne weitere externe Hardware möglich.
- Du nimmst einen zweiten ESP32 für den Datenempfang.
würde ich so machen:
mittels NTP die Zeit aus dem Internet holen,
in eine Datei am Filesystem des ESP mit append neue Zeilen dazu schreiben
eine Download-Möglichkeit der Datei vom ESP bereitstellen
Hallo,
wie schnell muss das denn sein können. Wenn das ehr langsam ist geht eventuell ja auch FTP auf einer NAS Platte.
Heinz
Wichtig: FTP kann nur ganze Dateien übertragen.
Gruß Tommy
und dann sind die Daten auf dem zweiten ESP ?
Ich hätt 2 da.
Aber dann sind sie ja immernoch auf dem ESP...
Hallo, wiso append geht da auch.
Gruß Heinz
Und wo in Deinem Link steht das Gegenteil meiner Aussage?
Oder hast Du diese nur nicht verstanden?
Es kann nur die ganze Datei hochgeladen werden
Gruß Tommy
Ja.
Was willst Du denn testen? Wie man die GPIOs auswertet? Wie man das Ergebnis in eine Datei schreibt? Wie man Daten von A nach B überträgt?
Minimal hast Du einen ESP32, schreibst das Ergebnis in eine Datei in das Dateisysten SPIFFS oder LittleFS dieses ESPs und überträgst diese Datei dann auf den PC. Schau mal nach dem Datei Manager von Fips.
Hallo,
ich denke wir reden aneinander vorbei. Meine Idee war immer dann wenn ein Ereignis auftritt eine Zeile mit append in eine Datei auf einer NAS anzuhängen , meinetwegen im CSV Format. Es kann sein das ich Deine Aussage nicht verstanden habe, aber wenn Du schreibst " FTP kann nur ganze Dateien" gibts da nicht viel Spielraum oder ? Und dann würde es append nicht geben können.
Gruß Heinz
Gnau das.
Gruß Tommy
Das kommt drauf an.
Es geht auch Append auf FTP.
ftp append
- 2 Minuten Lesedauer
Gilt für: Windows Server (halbjährlicher Kanal), Windows Server 2019, Windows Server 2016, Windows Server 2012 R2, Windows Server 2012
Fügt eine lokale Datei mithilfe der aktuellen Dateityp Einstellung an eine Datei auf dem Remote Computer an.
Nachzulesen u.a. bei Microsoft docs.
Ich habe vor kurzem einen super-simple-Datenlogger programmiert der UDP-messages an einen PC oder Raspi schickt auf dem ein Pythonscript läuft
// I wrote some basic documentation at the end of the file
#include <WiFi.h>
#include <PString.h>
char *ssid = "FRITZ!Box 7490";
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
char UDP_Msg_AoC[MaxMsgLength + 1]; // always remember one extra-char for terminating zero
PString UDP_Msg_PS(UDP_Msg_AoC, sizeof(UDP_Msg_AoC));
uint8_t UDP_Msg_uint8_Buffer[MaxMsgLength + 1]; // for some strange reasons on ESP32 the udp.write-function needs an uint8_t-array
#define MaxHeaderLength 64
char Header_AoC[MaxHeaderLength + 1]; // always remember one extra-char for terminating zero
PString Header_PS(Header_AoC, sizeof(Header_AoC));
#define MaxTimeStampLength 32
char TimeStamp_AoC[MaxTimeStampLength + 1]; // always remember one extra-char for terminating zero
PString TimeStamp_PS(TimeStamp_AoC, sizeof(TimeStamp_AoC));
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 StoreTimeStampStr(char* p_PointerToTarget, tm p_myTimeInfo) {
char l_TimeStamp_AoC[MaxTimeStampLength + 1]; // always remember one extra-char for terminating zero
PString l_TimeStamp_PS(l_TimeStamp_AoC, sizeof(l_TimeStamp_AoC));
time(&now); // read the current time
localtime_r(&now, &myTimeInfo);
l_TimeStamp_PS = p_myTimeInfo.tm_year + 1900;
l_TimeStamp_PS += ".";
l_TimeStamp_PS += p_myTimeInfo.tm_mon + 1;
l_TimeStamp_PS += ".";
l_TimeStamp_PS += p_myTimeInfo.tm_mday;
l_TimeStamp_PS += ", ";
l_TimeStamp_PS += p_myTimeInfo.tm_hour;
l_TimeStamp_PS += ":";
l_TimeStamp_PS += p_myTimeInfo.tm_min;
l_TimeStamp_PS += ":";
l_TimeStamp_PS += p_myTimeInfo.tm_sec;
l_TimeStamp_PS += ",";
strlcpy(p_PointerToTarget, l_TimeStamp_AoC,l_TimeStamp_PS.length() + 1);
}
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_PS = "myDemoHeader";
}
void PrintMsg() {
Serial.print("UDP_Msg_PS #");
Serial.print(UDP_Msg_PS);
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_PS = Header_PS;
UDP_Msg_PS += HeaderDelimiter;
UDP_Msg_PS += "myUserData, ";
StoreTimeStampStr(TimeStamp_AoC,myTimeInfo);
UDP_Msg_PS += TimeStamp_PS;
UDP_Msg_PS += myCounter++;
Serial.print("Send UDP_Msg #");
Serial.print(UDP_Msg_PS);
Serial.println("#");
memcpy(UDP_Msg_uint8_Buffer,UDP_Msg_PS,UDP_Msg_PS.length()); // for some strange reason the ESP32 UDP-function write needs an uint8_t-array
Udp.beginPacket(remoteIP, remotePort);
Udp.write(UDP_Msg_uint8_Buffer, UDP_Msg_PS.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 PString-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"
*/
Der Code enthält auch das pythonscript als Block-Kommentar
Was hindert Dich zum Entwickeln einen XAMPP auf Deinem PC zu installieren? Da hast Du Webserver, Datenbank und einiges Andere. Aufwand Downloadzeit + 3 Minuten.
Das halte ich für ziemlich übertrieben das das für einen Anfänger in drei Minuten fertig ist. Wenn das so schnell geht dann müsste es ja irgendwo eine 5 screenshots kurze Anleitung geben. Kannste mal eben den Link dazu posten oder das 3 Minuten Youtube-Video?
Ich gebe mich jetzt mal ungehemmt meinen Vorurteilen hin: Schon der Name XAMPP hört sich nach Linux / consolentool und stundenlangem wälzen von per /man Befehl aufgerufenen kryptischen Parameterlisten an.
viele Grüße Stefan
XAMPP ist klicksi-klicksi.
dann noch die ini suchen die einen Zugriff außer localhost zuläst.
Diesen Punkt schätze ich gleich schwierig ein wie eine Python installation.
Aber jetzt braucht es erst mal eine Rückmeldung vom Threadowner, welchen der Vorschläge er genau machen will. Weil er ja anfänglich Raspi, Web ... ausgeschlossen hat, dann fällt wohl NAS auch weg.
Danke erstmal für die ganzen Anregungen.
Habe mal xampp probiert, da scheitert es schon am Verbinden des Apache Moduls.
Bin auf ein relativ umfangreiches Tutorial gestossen:
https://plantprogrammer.de/esp32-rfid-and-mqtt/
Das werde ich jetzt erst einmal durcharbeiten, da meine Grundkenntnisse in der Thematik echt dürftig sind.
Zu den reinen Zeitstempeln muss auch irgendwie eine Zuordnung stattfinden, da ist der beinhaltende Exkurs zum RFID vllt auch eine Hilfe.
Hätte gern eine Lösung die nur mit den ESP32 modulen auskommt.
Werde mich auch mit den Übergabemöglichkeiten auseinandersetzen müssen, habe in dem Bereich auch garkeine Ahnung wie das mit protokollen usw läuft.
Dazu werd ich mich dann mal über den Datei Manager von Fips schlau machen.

Gilt für: Windows Server (halbjährlicher Kanal), Windows Server 2019, Windows Server 2016, Windows Server 2012 R2, Windows Server 2012
Das gilt aber nicht für jeden FTP-Server und da unser TO ja keinen Server (und damit wohl auch keinen von MS) aufsetzen will, ist das irrelevant.
Gruß Tommy