Transferring CSV Files from S7-1500 SIMATIC Memory Card to IOT2040
This reference covers the end-to-end path required to move a CSV data-log file written by a SIMATIC S7-1500 CPU onto its SIMATIC Memory Card, copy it to a SIMATIC IOT2040 gateway, package the file with a ZIP utility, push it to a remote FTP server, and then perform the reverse flow so that files coming back from the server are unzipped and written back to the S7-1500. The implementation uses the open web server of the S7-1500, the Node-RED runtime on the IOT2040, and standard Linux command-line tools (wget, curl, zip, unzip) available in the IOT2000 Yocto image.
curl/wget, and connect to plant networks on one side and IT networks on the other.1. Architecture Overview
The integration consists of three logical zones:
-
OT zone — the S7-1500 CPU (for example 6ES7515-2AM02-0AB0 or 6ES7513-1AL02-0AB0) with a SIMATIC Memory Card (for example 6ES7954-8LE03-0AA0, 12 MB) hosting the active
DataLog. - Edge zone — the SIMATIC IOT2040 (6ES7647-0AA00-1YA2), running the IOT2000 SD card image with Node-RED pre-installed. It pulls the CSV, compresses it, and forwards it.
- IT zone — a remote FTP/HTTPS server that stores the archive and pushes new parameter or recipe CSVs back to the line.
The data path for outbound logs is:
S7-1500 DataLog (.csv) → /Memory Card/DATALOG/datalog.csv
│
│ (S7-1500 integrated Web Server, "User-defined Web pages")
▼
IOT2040 /home/root/datalog.csv (pulled by Node-RED exec → wget)
│
│ (zip -j datalog.zip datalog.csv)
▼
IOT2040 /home/root/datalog.zip
│
│ (curl -T → FTP / SFTP / HTTPS)
▼
Remote server: /upload/<plant>/<timestamp>.zip
The inbound path is the mirror image, terminating in the S7-1500 via a user-defined web page PUT/POST or via an S7 PUT/GET trigger.
2. Prerequisites
| Item | Requirement | Notes |
|---|---|---|
| S7-1500 CPU firmware | V2.0 or higher (V2.6+ recommended) | Required for integrated Web Server and user-defined pages |
| SIMATIC Memory Card | 6ES7954-8LE03-0AA0 (12 MB) or larger | Format is FAT32; DataLog directory is created automatically |
| TIA Portal | V16 or higher with S7-1500 support package | For programming the DataLog and web page fragments |
| SIMATIC IOT2040 | 6ES7647-0AA00-1YA2, image V2.6.0 or higher | Includes Node-RED 0.20.x |
| Network | OT and IOT2040 on same subnet; outbound to FTP server allowed | Use a separate interface if DMZ is required |
| Credentials | FTP user, password, server URL; PLC web-server user with read | Avoid cleartext FTP across WAN if possible |
3. S7-1500 DataLog Configuration in TIA Portal
The S7-1500 DataLog function block family writes comma-separated files onto the SIMATIC Memory Card under /<Card>/DataLog/<name>.csv. The required programming steps are:
- In the CPU's Properties → Web server, enable Enable Web server on the CPU, set Permit access only via HTTPS if needed, and create a user with the Read files right.
- Add a DataLogCreate instance (FB 1000) in your program and define the columns matching your process tags.
- Call DataLogOpen (FB 1001) once at startup; call DataLogWrite (FB 1002) cyclically or on event; call DataLogClose (FB 1003) on controlled shutdown.
- Optionally, configure DataLogNewFile (FB 1004) to roll the file on size or time.
Minimal ladder snippet for the open + header cycle:
// STL / SCL equivalent
IF "FirstScan" THEN
DataLogCreate_Instance(MODE := 1, // create new file
NAME := 'datalog',
HEADER := 'Timestamp;Pressure;Temp;Flow',
DATA := 'MyData',
ID := "LogID");
END_IF;
IF "StartLog" AND NOT "LogBusy" THEN
DataLogOpen_Instance(MODE := 1, NAME := 'datalog', ID := "LogID");
END_IF;
// Write trigger every 1 s
IF "Tick1s" THEN
DataLogWrite_Instance(ID := "LogID", DATA := "MyData");
END_IF;
After compiling and downloading, verify the file by going to the S7-1500 Web Server (browser: http://<plc-ip>/), logging in, and drilling into Files → DataLog → datalog.csv. A valid session token is required for any non-browser HTTP client.
4. SIMATIC IOT2040 Setup
On the IOT2040, confirm Node-RED and the Linux utilities are present:
root@iot2040:~# opkg list-installed | grep -E 'wget|curl|zip|node-red'
root@iot2040:~# node-red --version
Node-RED 0.20.x
root@iot2040:~# which wget curl zip unzip
/usr/bin/wget
/usr/bin/curl
/usr/bin/zip
/usr/bin/unzip
If a package is missing, install it with opkg update && opkg install <name>. Create a working directory with predictable permissions:
mkdir -p /home/root/iot/queue /home/root/iot/archive
chmod 755 /home/root/iot
5. Pulling the CSV from the S7-1500 Web Server
The S7-1500's web server presents the DataLog directory under a hashed URL once you are logged in. Capture the file with a Node-RED exec node that calls wget. The trick is two-step authentication: first POST credentials, then GET the file with the resulting cookie.
Step 1 — obtain a session cookie and write it to a file:
curl -c /home/root/iot/cookies.txt \
-d 'Login=<user>&Password=<pass>' \
http://<plc-ip>/FormLogin
Step 2 — fetch the CSV with the cookie. The exact path on the web server for a DataLog file looks like:
wget --load-cookies /home/root/iot/cookies.txt \
-O /home/root/iot/datalog.csv \
'http://<plc-ip>/DataLog/datalog.csv?Action=DownloadFile&FileName=datalog.csv'
A clean Node-RED flow using the exec node looks like this in JSON form (paste via Import → Clipboard):
[{"id":"f1","type":"inject","name":"Hourly tick","topic":"","payload":"","payloadType":"date","repeat":"3600","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":140,"wires":[["f2"]]},
{"id":"f2","type":"exec","name":"wget datalog.csv","command":"wget --load-cookies /home/root/iot/cookies.txt -O /home/root/iot/datalog.csv 'http://<plc-ip>/DataLog/datalog.csv?Action=DownloadFile&FileName=datalog.csv'","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"x":360,"y":140,"wires":[["f3"],[],[]]},
{"id":"f3","type":"exec","name":"zip archive","command":"cd /home/root/iot && zip -j /home/root/iot/datalog.zip datalog.csv","x":580,"y":140,"wires":[["f4"],[],[]]},
{"id":"f4","type":"exec","name":"curl -T to FTP","command":"curl -T /home/root/iot/datalog.zip ftp://user:pass@server/plant1/ --ftp-create-dirs","x":800,"y":140,"wires":[[],[],[]]}]
Key flags in the above flow:
-
--load-cookiesreuses the session that the PLC returned in step 1; without it the CSV responds with HTTP 401. -
-Owrites to a known local path; never use-Phere because the IOT2040's home partition is small. -
zip -jstrips the directory prefix so the archive contains onlydatalog.csv. -
curl -Tperforms an FTP upload, creating remote directories with--ftp-create-dirs.
wget is more forgiving about redirect chains and stale tokens than curl. For the outbound path you have to use curl -T because wget cannot PUT files by design. Make sure to pass the explicit ftp:// scheme and credentials, and that the server accepts passive mode on TCP 50000-50100.6. Compression and FTP Upload
Although ZIP is convenient, tar.gz is smaller and avoids licensing noise. A typical production script does the following each cycle:
- Rotate the previous local archive into
/home/root/iot/archive/<timestamp>.zip. - Refresh
datalog.csvfrom the PLC. - Compress and upload with a unique remote name.
- Remove the local copy after a 200/226 server response.
Bash equivalent run from a exec node:
#!/bin/sh
STAMP=$(date -u +%Y%m%dT%H%M%SZ)
LOG=/home/root/iot/datalog.csv
OUT=/home/root/iot/datalog_${STAMP}.zip
# 1. refresh session
curl -s -c /home/root/iot/cookies.txt \
-d 'Login=plcuser&Password=plcpass' \
http://10.0.0.10/FormLogin > /dev/null
# 2. download latest csv
wget -q --load-cookies /home/root/iot/cookies.txt \
-O $LOG \
'http://10.0.0.10/DataLog/datalog.csv?Action=DownloadFile&FileName=datalog.csv'
# 3. zip
zip -j -q $OUT $LOG
# 4. upload
curl -s -T $OUT ftp://ftpuser:ftppass@ftpsrv/plant1/$STAMP/ --ftp-create-dirs
RC=$?
# 5. archive locally if upload ok
[ $RC -eq 0 ] && mv $OUT /home/root/iot/archive/ || echo "FTP fail rc=$RC" >> /home/root/iot/log.txt
For SFTP instead of FTP, swap the last step for:
sftp -o StrictHostKeyChecking=no ftpuser@ftpsrv <<EOF
put $OUT /plant1/$STAMP/${STAMP}.zip
bye
EOF
For HTTPS REST endpoints use curl -F "file=@$OUT" https://api.example.com/upload with a bearer token in -H "Authorization: Bearer ...".
7. Receiving Files from the FTP Server (Inbound Path)
The reverse path is symmetrical. A second Node-RED flow polls the FTP server, downloads new ZIP files into /home/root/iot/inbox/, unzips them, and writes the resulting CSV back to the S7-1500. The trickiest part is writing the file back to the PLC because the S7-1500's web server does not support generic PUT on DataLog files. Use one of two supported mechanisms:
7.1 Method A — S7 PUT/GET
Enable Permit access with PUT/GET communication from remote partner in the CPU's Properties → Communication. The IOT2040 can use the open-source snap7 library or a Node-RED node-red-contrib-s7 node to write the CSV contents to a data block on the S7-1500. The PLC then re-creates the file with DataLogNewFile on the next scan.
7.2 Method B — User-defined web page with file upload
From TIA Portal, create a user-defined web page (Web server → User-defined pages) with a small HTML form that posts a file. Then call it with curl -F:
curl -F "file=@/home/root/iot/inbox/recipe.csv" \
-b /home/root/iot/cookies.txt \
http://<plc-ip>/<UserDefinedPage>/upload.html
The S7-1500 web page invokes a custom WWW instruction in the user program to copy the file into a configured DataLog directory or to a recipe DB.
8. End-to-End Flow Summary
| Step | Tool | Command / Action | Direction |
|---|---|---|---|
| 1. Authenticate | curl | POST /FormLogin with user/password | IOT2040 → S7-1500 |
| 2. Download CSV | wget | GET /DataLog/datalog.csv with cookies | S7-1500 → IOT2040 |
| 3. Compress | zip | zip -j datalog.zip datalog.csv | local |
| 4. Upload | curl / sftp | PUT to FTP server / SFTP server / HTTPS API | IOT2040 → IT |
| 5. Poll inbound | curl / sftp | GET list, download new ZIPs | IT → IOT2040 |
| 6. Decompress | unzip | unzip -o inbound.zip -d inbox/ | local |
| 7. Write to PLC | curl PUT or S7 PUT | POST user-defined page or write DB | IOT2040 → S7-1500 |
9. Verification and Diagnostics
Use this checklist before going into production:
-
File size sanity — confirm
ls -l /home/root/iot/datalog.csvshows a non-zero file that grows after each tick. -
CSV header check —
head -1 /home/root/iot/datalog.csvshould match theHEADERstring from DataLogCreate. - Cookie validity — the S7-1500 default session is 30 minutes. If the cycle is longer, re-authenticate each iteration.
-
FTP return code —
curl -von the first run; expect226 Transfer complete. -
Round trip — download a file you uploaded, unzip, diff the CSV against the local source with
diff -q local.csv remote.csv.
Common Failure Matrix
| Symptom | Likely Cause | Fix |
|---|---|---|
| wget returns 401 Unauthorized | Stale cookie or wrong user right | Re-run FormLogin, confirm user has Read files in TIA Portal |
| wget returns 404 on DataLog path | DataLog not created yet | Trigger DataLogCreate once, then DataLogOpen |
| curl -T connection refused | FTP passive ports blocked on firewall | Open 50000-50100, or use SFTP/FTPS explicit |
| curl -T hangs after login | Server requires explicit FTPS (TLS) | Use curl --ssl-reqd -T and ftps://
|
| Empty CSV (0 bytes) | DataLog was closed between cycles | Re-open on every cycle, or check shutdown logic |
| Unzip fails on IOT2040 | unzip not installed | opkg install unzip |
| PUT to PLC returns 405 | User-defined page not enabled | Enable User-defined web pages in TIA Portal, download HTML |
10. Performance and Timing Notes
Typical timings on an IOT2040 (single-core 600 MHz ARM, 1 GB RAM):
- FormLogin round trip: 50–120 ms on the same VLAN.
- 100 kB CSV download: 200–400 ms.
- zip -j of 100 kB: < 30 ms.
- curl -T of 100 kB: 300–800 ms depending on WAN RTT.
For larger files (multiple MB) raise the exec node timeout to 60 s and avoid concurrent transfers — the IOT2040 has a single NIC and limited CPU.
11. Field-Proven Caveats
- The S7-1500 file system path for DataLog is case-sensitive on newer firmware; use lowercase
datalog.csvconsistently. - When the PLC is in STOP, the web server still serves files but the DataLog is not updated; your script will keep reading the same file.
- Avoid
rmon the SIMATIC Memory Card from the IOT2040; the PLC manages its own retention. - Node-RED flows persist at
/home/root/.node-red/flows_<host>.json; back this up before firmware updates.
What SIMATIC Memory Card size do I need for S7-1500 data logging?
For most CSV data logs, a 12 MB card (6ES7954-8LE03-0AA0) is sufficient. If you log high-frequency process values without rollover, step up to 32 MB (6ES7954-8LL03-0AA0). Always retain at least 30% free space to avoid write errors.
Why does wget work for downloading the CSV from the S7-1500 but curl fails?
Wget transparently follows the S7-1500 web server's session redirects and accepts self-signed certificates with --no-check-certificate. Curl needs the cookie jar, a fixed user-agent, and proper handling of the 30-minute session expiry. Re-authenticate before every download for long-running scripts.
How do I push a ZIP file from the IOT2040 to an FTP server from Node-RED?
Use an exec node running curl -T /home/root/iot/file.zip ftp://user:pass@server/path/ --ftp-create-dirs. Add --ssl-reqd and switch the scheme to ftps:// if the server requires TLS, and open passive-mode ports 50000-50100 on the firewall.
Can the S7-1500 directly write a file received from the IOT2040?
Yes, through a user-defined web page with a file-upload form. The page calls a WWW instruction in your STEP 7 program that copies the uploaded file to a configured directory or to a DataLog buffer. The IOT2040 uses curl -F "file=@path" -b cookies.txt to post to the page.
What is the difference between a Program card and a Firmware card for storing CSVs?
A Program card holds the STEP 7 project and user DataLogs; this is the typical configuration. A Firmware update card is for CPU firmware only and should not be used as a data-log destination. Set the card type in TIA Portal under CPU → Properties → SIMATIC Memory Card and use a SIMATIC Memory Card of the recommended size for your log volume.