Subversion Repositories ESP8266_P1_Meter

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 raymond 1
// SPDX-License-Identifier: LGPL-3.0-or-later
2
// Copyright 2016-2026 Hristo Gochkov, Mathieu Carbou, Emil Muratov, Will Miles
3
 
4
//
5
// Demo to upload a firmware and filesystem image via multipart form data
6
//
7
 
8
#include <Arduino.h>
9
#if defined(ESP32) || defined(LIBRETINY)
10
#include <AsyncTCP.h>
11
#include <WiFi.h>
12
#elif defined(ESP8266)
13
#include <ESP8266WiFi.h>
14
#include <ESPAsyncTCP.h>
15
#elif defined(TARGET_RP2040) || defined(TARGET_RP2350) || defined(PICO_RP2040) || defined(PICO_RP2350)
16
#include <RPAsyncTCP.h>
17
#include <WiFi.h>
18
#endif
19
 
20
#include <ESPAsyncWebServer.h>
21
#include <StreamString.h>
22
#include <LittleFS.h>
23
 
24
// ESP32 example ONLY
25
#ifdef ESP32
26
#include <Update.h>
27
#endif
28
 
29
static AsyncWebServer server(80);
30
 
31
void setup() {
32
  Serial.begin(115200);
33
 
34
  if (!LittleFS.begin()) {
35
    LittleFS.format();
36
    LittleFS.begin();
37
  }
38
 
39
#if ASYNCWEBSERVER_WIFI_SUPPORTED
40
  WiFi.mode(WIFI_AP);
41
  WiFi.softAP("esp-captive");
42
#endif
43
 
44
// ESP32 example ONLY
45
#ifdef ESP32
46
 
47
  // Shows how to get the fw and fs  (names) and filenames from a multipart upload,
48
  // and also how to handle multiple file uploads in a single request.
49
  //
50
  // This example also shows how to pass and handle different parameters having the same name in query string, post form and content-disposition.
51
  //
52
  // Execute in the terminal, in order:
53
  //
54
  // 1. Build firmware: pio run -e arduino-3
55
  // 2. Build FS image: pio run -e arduino-3 -t buildfs
56
  // 3. Flash both at the same time: curl -v -F "name=Bob" -F "fw=@.pio/build/arduino-3/firmware.bin" -F "fs=@.pio/build/arduino-3/littlefs.bin" http://192.168.4.1/flash?name=Bill
57
  //
58
  server.on(
59
    "/flash", HTTP_POST,
60
    [](AsyncWebServerRequest *request) {
61
      if (request->getResponse()) {
62
        // response already created
63
        return;
64
      }
65
 
66
      // list all parameters
67
      Serial.println("Request parameters:");
68
      const size_t params = request->params();
69
      for (size_t i = 0; i < params; i++) {
70
        const AsyncWebParameter *p = request->getParam(i);
71
        Serial.printf("Param[%u]: %s=%s, isPost=%d, isFile=%d, size=%u\n", i, p->name().c_str(), p->value().c_str(), p->isPost(), p->isFile(), p->size());
72
      }
73
 
74
      Serial.println("Flash / Filesystem upload completed");
75
 
76
      request->send(200, "text/plain", "Upload complete");
77
    },
78
    [](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
79
      Serial.printf("Upload[%s]: index=%u, len=%u, final=%d\n", filename.c_str(), index, len, final);
80
 
81
      if (request->getResponse() != nullptr) {
82
        // upload aborted
83
        return;
84
      }
85
 
86
      // start a new content-disposition upload
87
      if (!index) {
88
        // list all parameters
89
        const size_t params = request->params();
90
        for (size_t i = 0; i < params; i++) {
91
          const AsyncWebParameter *p = request->getParam(i);
92
          Serial.printf("Param[%u]: %s=%s, isPost=%d, isFile=%d, size=%u\n", i, p->name().c_str(), p->value().c_str(), p->isPost(), p->isFile(), p->size());
93
        }
94
 
95
        // get the content-disposition parameter
96
        const AsyncWebParameter *p = request->getParam(asyncsrv::T_name, true, true);
97
        if (p == nullptr) {
98
          request->send(400, "text/plain", "Missing content-disposition 'name' parameter");
99
          return;
100
        }
101
 
102
        // determine upload type based on the parameter name
103
        if (p->value() == "fs") {
104
          Serial.printf("Filesystem image upload for file: %s\n", filename.c_str());
105
          if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_SPIFFS)) {
106
            Update.printError(Serial);
107
            request->send(400, "text/plain", "Update begin failed");
108
            return;
109
          }
110
 
111
        } else if (p->value() == "fw") {
112
          Serial.printf("Firmware image upload for file: %s\n", filename.c_str());
113
          if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASH)) {
114
            Update.printError(Serial);
115
            request->send(400, "text/plain", "Update begin failed");
116
            return;
117
          }
118
 
119
        } else {
120
          Serial.printf("Unknown upload type for file: %s\n", filename.c_str());
121
          request->send(400, "text/plain", "Unknown upload type");
122
          return;
123
        }
124
      }
125
 
126
      // some bytes to write ?
127
      if (len) {
128
        if (Update.write(data, len) != len) {
129
          Update.printError(Serial);
130
          Update.end();
131
          request->send(400, "text/plain", "Update write failed");
132
          return;
133
        }
134
      }
135
 
136
      // finish the content-disposition upload
137
      if (final) {
138
        if (!Update.end(true)) {
139
          Update.printError(Serial);
140
          request->send(400, "text/plain", "Update end failed");
141
          return;
142
        }
143
 
144
        // success response is created in the final request handler when all uploads are completed
145
        Serial.printf("Upload success of file %s\n", filename.c_str());
146
      }
147
    }
148
  );
149
 
150
#endif
151
 
152
  server.begin();
153
}
154
 
155
// not needed
156
void loop() {
157
  delay(100);
158
}