mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-19 23:22:16 +03:00
ESP8266HTTPUpdate: Get available firmware version from update server (#8968)
* added getAvailableVersion(), moved _httpClientTimeout and _followRedirects to protected, added enum HTTPUpdateError * auto numbering of HTTPUpdateError enum * added getAvailableVersion(), debug output current current Sketch MD5 * updated advanced updater php script * switch case indention corrected * Revert "added getAvailableVersion(), debug output current current Sketch MD5" This reverts commit 60d2c7762e7fb1fed7fae37fa99be149e12f125c. * Revert "auto numbering of HTTPUpdateError enum" This reverts commit 61785b27da3f2d42f8f95316d78ce22e5b00103a. * Revert "added getAvailableVersion(), moved _httpClientTimeout and _followRedirects to protected, added enum HTTPUpdateError" This reverts commit cec84ed17ab149d3e48082293f9e2723246b7d0b. * corrected incorrect merge with master
This commit is contained in:
parent
30c6df4639
commit
fb8d6d668d
@ -592,34 +592,42 @@ With this information the script now can check if an update is needed. It is als
|
|||||||
|
|
||||||
<?PHP
|
<?PHP
|
||||||
|
|
||||||
header('Content-type: text/plain; charset=utf8', true);
|
|
||||||
|
|
||||||
function check_header($name, $value = false) {
|
function check_header($name, $value = false) {
|
||||||
if(!isset($_SERVER[$name])) {
|
global $headers;
|
||||||
|
if (!isset($headers[$name])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if($value && $_SERVER[$name] != $value) {
|
if ($value && $headers[$name] != $value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendFile($path) {
|
function sendFile($path, $version) {
|
||||||
header($_SERVER["SERVER_PROTOCOL"].' 200 OK', true, 200);
|
header($_SERVER["SERVER_PROTOCOL"].' 200 OK', true, 200);
|
||||||
header('Content-Type: application/octet-stream', true);
|
header('Content-Type: application/octet-stream', true);
|
||||||
header('Content-Disposition: attachment; filename='.basename($path));
|
header('Content-Disposition: attachment; filename='.basename($path));
|
||||||
header('Content-Length: '.filesize($path), true);
|
header('Content-Length: '.filesize($path), true);
|
||||||
header('x-MD5: '.md5_file($path), true);
|
header('x-MD5: '.md5_file($path), true);
|
||||||
|
header('x-version: '.$version, true);
|
||||||
readfile($path);
|
readfile($path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!check_header('User-Agent', 'ESP8266-http-Update')) {
|
|
||||||
|
$headers = getallheaders();
|
||||||
|
|
||||||
|
header('Content-type: text/plain; charset=utf8', true);
|
||||||
|
|
||||||
|
//if (!check_header('HTTP_USER_AGENT', 'ESP8266-http-Update')) {
|
||||||
|
if (!check_header('User-Agent', 'ESP8266-http-Update')) {
|
||||||
header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden', true, 403);
|
header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden', true, 403);
|
||||||
echo "only for ESP8266 updater!\n";
|
echo "Only for ESP8266 updater!\n";
|
||||||
|
echo "User-Agent: ".$headers['User-Agent']." != ESP8266-http-Update\n";
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(
|
if (
|
||||||
|
!check_header('x-ESP8266-mode') ||
|
||||||
!check_header('x-ESP8266-STA-MAC') ||
|
!check_header('x-ESP8266-STA-MAC') ||
|
||||||
!check_header('x-ESP8266-AP-MAC') ||
|
!check_header('x-ESP8266-AP-MAC') ||
|
||||||
!check_header('x-ESP8266-free-space') ||
|
!check_header('x-ESP8266-free-space') ||
|
||||||
@ -629,32 +637,54 @@ With this information the script now can check if an update is needed. It is als
|
|||||||
!check_header('x-ESP8266-sdk-version')
|
!check_header('x-ESP8266-sdk-version')
|
||||||
) {
|
) {
|
||||||
header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden', true, 403);
|
header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden', true, 403);
|
||||||
echo "only for ESP8266 updater! (header)\n";
|
echo "Only for ESP8266 updater! (header missing)\n";
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$db = array(
|
$db_string = '{
|
||||||
"18:FE:AA:AA:AA:AA" => "DOOR-7-g14f53a19",
|
"18:FE:AA:AA:AA:AA": {"file": "DOOR-7-g14f53a19.bin", "version": 1},
|
||||||
"18:FE:AA:AA:AA:BB" => "TEMP-1.0.0"
|
"18:FE:AA:AA:AA:BB": {"file": "TEMP-1.0.0".bin", "version": 1}}';
|
||||||
);
|
// $db_string = file_get_contents("arduino-db.json");
|
||||||
|
$db = json_decode($db_string, true);
|
||||||
if(!isset($db[$_SERVER['x-ESP8266-STA-MAC']])) {
|
$mode = $headers['x-ESP8266-mode'];
|
||||||
header($_SERVER["SERVER_PROTOCOL"].' 500 ESP MAC not configured for updates', true, 500);
|
$mac = $headers['x-ESP8266-STA-MAC'];
|
||||||
|
|
||||||
|
if (!isset($db[$mac])) {
|
||||||
|
header($_SERVER["SERVER_PROTOCOL"].' 404 ESP MAC not configured for updates', true, 404);
|
||||||
|
echo "MAC ".$mac." not configured for updates\n";
|
||||||
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$localBinary = "./bin/".$db[$_SERVER['x-ESP8266-STA-MAC']].".bin";
|
$localBinary = $db[$mac]['file'];
|
||||||
|
$localVersion = $db[$mac]['version'];
|
||||||
// Check if version has been set and does not match, if not, check if
|
|
||||||
// MD5 hash between local binary and ESP8266 binary do not match if not.
|
if (!is_readable($localBinary)) {
|
||||||
// then no update has been found.
|
header($_SERVER["SERVER_PROTOCOL"].' 404 File not found', true, 404);
|
||||||
if((!check_header('x-ESP8266-sdk-version') && $db[$_SERVER['x-ESP8266-STA-MAC']] != $_SERVER['x-ESP8266-version'])
|
echo "File ".$localBinary." not found\n";
|
||||||
|| $_SERVER["x-ESP8266-sketch-md5"] != md5_file($localBinary)) {
|
exit();
|
||||||
sendFile($localBinary);
|
}
|
||||||
|
|
||||||
|
if ($mode == 'sketch') {
|
||||||
|
// Check if version has been set and does not match, if not, check if
|
||||||
|
// MD5 hash between local binary and ESP8266 binary do not match if not.
|
||||||
|
// then no update has been found.
|
||||||
|
if ((check_header('x-ESP8266-version') && $headers['x-ESP8266-version'] != $localVersion)) {
|
||||||
|
// || $headers["x-ESP8266-sketch-md5"] != md5_file($localBinary)) {
|
||||||
|
sendFile($localBinary, $localVersion);
|
||||||
|
} else {
|
||||||
|
header($_SERVER["SERVER_PROTOCOL"].' 304 Not Modified', true, 304);
|
||||||
|
echo "File ".$localBinary." not modified\n";
|
||||||
|
}
|
||||||
|
} else if ($mode == 'version') {
|
||||||
|
header($_SERVER["SERVER_PROTOCOL"].' 200 OK', true, 200);
|
||||||
|
header('x-MD5: '.md5_file($localBinary), true);
|
||||||
|
header('x-version: '.$localVersion, true);
|
||||||
} else {
|
} else {
|
||||||
header($_SERVER["SERVER_PROTOCOL"].' 304 Not Modified', true, 304);
|
header($_SERVER["SERVER_PROTOCOL"].' 404 Mode not supported', true, 404);
|
||||||
|
echo "mode: ".$mode." not supported\n";
|
||||||
|
exit();
|
||||||
}
|
}
|
||||||
|
?>
|
||||||
header($_SERVER["SERVER_PROTOCOL"].' 500 no version for ESP MAC', true, 500);
|
|
||||||
|
|
||||||
Stream Interface
|
Stream Interface
|
||||||
----------------
|
----------------
|
||||||
|
@ -235,6 +235,7 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String&
|
|||||||
DEBUG_HTTP_UPDATE("[httpUpdate] ESP8266 info:\n");
|
DEBUG_HTTP_UPDATE("[httpUpdate] ESP8266 info:\n");
|
||||||
DEBUG_HTTP_UPDATE("[httpUpdate] - free Space: %d\n", ESP.getFreeSketchSpace());
|
DEBUG_HTTP_UPDATE("[httpUpdate] - free Space: %d\n", ESP.getFreeSketchSpace());
|
||||||
DEBUG_HTTP_UPDATE("[httpUpdate] - current Sketch Size: %d\n", ESP.getSketchSize());
|
DEBUG_HTTP_UPDATE("[httpUpdate] - current Sketch Size: %d\n", ESP.getSketchSize());
|
||||||
|
DEBUG_HTTP_UPDATE("[httpUpdate] - current Sketch MD5: %s\n", ESP.getSketchMD5().c_str());
|
||||||
|
|
||||||
if(currentVersion && currentVersion[0] != 0x00) {
|
if(currentVersion && currentVersion[0] != 0x00) {
|
||||||
DEBUG_HTTP_UPDATE("[httpUpdate] - current version: %s\n", currentVersion.c_str() );
|
DEBUG_HTTP_UPDATE("[httpUpdate] - current version: %s\n", currentVersion.c_str() );
|
||||||
@ -440,6 +441,115 @@ bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, const String& md5,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get avialable firmware version from update server
|
||||||
|
* @author Holger Mueller
|
||||||
|
* @date 2023-08-03
|
||||||
|
*
|
||||||
|
* @param client WiFiClient to use (see HTTPClient::begin)
|
||||||
|
* @param host Update host name or IP (see HTTPClient::begin)
|
||||||
|
* @param port Port on host (see HTTPClient::begin)
|
||||||
|
* @param uri Update URI on server (see HTTPClient::begin)
|
||||||
|
* @param current_version Current firmware version
|
||||||
|
* @param available_version Firmware version available on update server
|
||||||
|
* @return ESP8266HTTPUpdate::HTTPUpdateResult, HTTP_UPDATE_OK in case of success
|
||||||
|
*/
|
||||||
|
HTTPUpdateResult ESP8266HTTPUpdate::getAvailableVersion(WiFiClient& client, const String& host, uint16_t port, const String& uri, const String& current_version, String& available_version) {
|
||||||
|
HTTPUpdateResult ret = HTTP_UPDATE_FAILED;
|
||||||
|
HTTPClient http;
|
||||||
|
http.begin(client, host, port, uri);
|
||||||
|
|
||||||
|
// use HTTP/1.0 for update since the update handler not support any transfer Encoding
|
||||||
|
http.useHTTP10(true);
|
||||||
|
http.setTimeout(_httpClientTimeout);
|
||||||
|
http.setFollowRedirects(_followRedirects);
|
||||||
|
http.setUserAgent(F("ESP8266-http-Update"));
|
||||||
|
http.addHeader(F("x-ESP8266-Chip-ID"), String(ESP.getChipId()));
|
||||||
|
http.addHeader(F("x-ESP8266-STA-MAC"), WiFi.macAddress());
|
||||||
|
http.addHeader(F("x-ESP8266-AP-MAC"), WiFi.softAPmacAddress());
|
||||||
|
http.addHeader(F("x-ESP8266-free-space"), String(ESP.getFreeSketchSpace()));
|
||||||
|
http.addHeader(F("x-ESP8266-sketch-size"), String(ESP.getSketchSize()));
|
||||||
|
http.addHeader(F("x-ESP8266-sketch-md5"), String(ESP.getSketchMD5()));
|
||||||
|
http.addHeader(F("x-ESP8266-chip-size"), String(ESP.getFlashChipRealSize()));
|
||||||
|
http.addHeader(F("x-ESP8266-sdk-version"), ESP.getSdkVersion());
|
||||||
|
|
||||||
|
http.addHeader(F("x-ESP8266-mode"), F("version"));
|
||||||
|
|
||||||
|
if (current_version && current_version[0] != 0x00) {
|
||||||
|
http.addHeader(F("x-ESP8266-version"), current_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_user.isEmpty() && !_password.isEmpty()) {
|
||||||
|
http.setAuthorization(_user.c_str(), _password.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_auth.isEmpty()) {
|
||||||
|
http.setAuthorization(_auth.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* headerkeys[] = {"x-MD5", "x-version"};
|
||||||
|
size_t headerkeyssize = sizeof(headerkeys) / sizeof(char*);
|
||||||
|
|
||||||
|
// track these headers
|
||||||
|
http.collectHeaders(headerkeys, headerkeyssize);
|
||||||
|
|
||||||
|
int code = http.GET();
|
||||||
|
|
||||||
|
if (code <= 0) {
|
||||||
|
DEBUG_HTTP_UPDATE("[httpUpdate] HTTP error: %s\n", http.errorToString(code).c_str());
|
||||||
|
_setLastError(code);
|
||||||
|
http.end();
|
||||||
|
return HTTP_UPDATE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_HTTP_UPDATE("[httpUpdate] Header read fin.\n");
|
||||||
|
DEBUG_HTTP_UPDATE("[httpUpdate] Server header:\n");
|
||||||
|
DEBUG_HTTP_UPDATE("[httpUpdate] - code: %d\n", code);
|
||||||
|
DEBUG_HTTP_UPDATE("[httpUpdate] - len: %d\n", http.getSize());
|
||||||
|
if (code != HTTP_CODE_OK) {
|
||||||
|
DEBUG_HTTP_UPDATE("[httpUpdate] - payload: %s\n", http.getString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case HTTP_CODE_OK: ///< OK (check for version)
|
||||||
|
if (http.hasHeader("x-version")) {
|
||||||
|
available_version = http.header("x-version");
|
||||||
|
ret = HTTP_UPDATE_OK;
|
||||||
|
DEBUG_HTTP_UPDATE("[httpUpdate] - current version: %s\n", current_version.c_str());
|
||||||
|
DEBUG_HTTP_UPDATE("[httpUpdate] - server version: %s\n", available_version.c_str());
|
||||||
|
} else {
|
||||||
|
_setLastError(HTTP_UE_SERVER_NOT_REPORT_VERSION);
|
||||||
|
ret = HTTP_UPDATE_FAILED;
|
||||||
|
DEBUG_HTTP_UPDATE("[httpUpdate] Server did not respond with a firmware version\n");
|
||||||
|
}
|
||||||
|
if (http.hasHeader("x-MD5")) {
|
||||||
|
DEBUG_HTTP_UPDATE("[httpUpdate] - current Sketch MD5: %s\n", ESP.getSketchMD5().c_str());
|
||||||
|
DEBUG_HTTP_UPDATE("[httpUpdate] - server Sketch MD5: %s\n", http.header("x-MD5").c_str());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HTTP_CODE_NOT_FOUND:
|
||||||
|
_setLastError(HTTP_UE_SERVER_FILE_NOT_FOUND);
|
||||||
|
ret = HTTP_UPDATE_FAILED;
|
||||||
|
break;
|
||||||
|
case HTTP_CODE_FORBIDDEN:
|
||||||
|
_setLastError(HTTP_UE_SERVER_FORBIDDEN);
|
||||||
|
ret = HTTP_UPDATE_FAILED;
|
||||||
|
break;
|
||||||
|
case HTTP_CODE_UNAUTHORIZED:
|
||||||
|
_setLastError(HTTP_UE_SERVER_UNAUTHORIZED);
|
||||||
|
ret = HTTP_UPDATE_FAILED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_setLastError(HTTP_UE_SERVER_WRONG_HTTP_CODE);
|
||||||
|
ret = HTTP_UPDATE_FAILED;
|
||||||
|
DEBUG_HTTP_UPDATE("[httpUpdate] HTTP Code is (%d)\n", code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
http.end();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_HTTPUPDATE)
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_HTTPUPDATE)
|
||||||
ESP8266HTTPUpdate ESPhttpUpdate;
|
ESP8266HTTPUpdate ESPhttpUpdate;
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,16 +43,18 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// note we use HTTP client errors too so we start at 100
|
/// note we use HTTP client errors too so we start at 100
|
||||||
//TODO - in v3.0.0 make this an enum
|
enum HTTPUpdateError {
|
||||||
constexpr int HTTP_UE_TOO_LESS_SPACE = (-100);
|
HTTP_UE_SERVER_NOT_REPORT_VERSION = -109, // server did not respond with a firmware version
|
||||||
constexpr int HTTP_UE_SERVER_NOT_REPORT_SIZE = (-101);
|
HTTP_UE_SERVER_UNAUTHORIZED, // -108
|
||||||
constexpr int HTTP_UE_SERVER_FILE_NOT_FOUND = (-102);
|
HTTP_UE_BIN_FOR_WRONG_FLASH, // -107
|
||||||
constexpr int HTTP_UE_SERVER_FORBIDDEN = (-103);
|
HTTP_UE_BIN_VERIFY_HEADER_FAILED, // -106
|
||||||
constexpr int HTTP_UE_SERVER_WRONG_HTTP_CODE = (-104);
|
HTTP_UE_SERVER_FAULTY_MD5, // -105
|
||||||
constexpr int HTTP_UE_SERVER_FAULTY_MD5 = (-105);
|
HTTP_UE_SERVER_WRONG_HTTP_CODE, // -104
|
||||||
constexpr int HTTP_UE_BIN_VERIFY_HEADER_FAILED = (-106);
|
HTTP_UE_SERVER_FORBIDDEN, // -103
|
||||||
constexpr int HTTP_UE_BIN_FOR_WRONG_FLASH = (-107);
|
HTTP_UE_SERVER_FILE_NOT_FOUND, // -102
|
||||||
constexpr int HTTP_UE_SERVER_UNAUTHORIZED = (-108);
|
HTTP_UE_SERVER_NOT_REPORT_SIZE, // -101
|
||||||
|
HTTP_UE_TOO_LESS_SPACE // -100
|
||||||
|
};
|
||||||
|
|
||||||
enum HTTPUpdateResult {
|
enum HTTPUpdateResult {
|
||||||
HTTP_UPDATE_FAILED,
|
HTTP_UPDATE_FAILED,
|
||||||
@ -122,7 +124,9 @@ public:
|
|||||||
t_httpUpdate_return updateFS(WiFiClient& client, const String& url, const String& currentVersion = "");
|
t_httpUpdate_return updateFS(WiFiClient& client, const String& url, const String& currentVersion = "");
|
||||||
t_httpUpdate_return update(HTTPClient& httpClient, const String& currentVersion = "");
|
t_httpUpdate_return update(HTTPClient& httpClient, const String& currentVersion = "");
|
||||||
t_httpUpdate_return updateFS(HTTPClient& httpClient, const String& currentVersion = "");
|
t_httpUpdate_return updateFS(HTTPClient& httpClient, const String& currentVersion = "");
|
||||||
|
|
||||||
|
t_httpUpdate_return getAvailableVersion(WiFiClient& client, const String& host, uint16_t port, const String& uri, const String& current_version, String& available_version);
|
||||||
|
|
||||||
// Notification callbacks
|
// Notification callbacks
|
||||||
void onStart(HTTPUpdateStartCB cbOnStart) { _cbStart = cbOnStart; }
|
void onStart(HTTPUpdateStartCB cbOnStart) { _cbStart = cbOnStart; }
|
||||||
void onEnd(HTTPUpdateEndCB cbOnEnd) { _cbEnd = cbOnEnd; }
|
void onEnd(HTTPUpdateEndCB cbOnEnd) { _cbEnd = cbOnEnd; }
|
||||||
@ -153,10 +157,9 @@ protected:
|
|||||||
String _password;
|
String _password;
|
||||||
String _auth;
|
String _auth;
|
||||||
String _md5Sum;
|
String _md5Sum;
|
||||||
private:
|
|
||||||
int _httpClientTimeout;
|
int _httpClientTimeout;
|
||||||
followRedirects_t _followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS;
|
followRedirects_t _followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS;
|
||||||
|
private:
|
||||||
// Callbacks
|
// Callbacks
|
||||||
HTTPUpdateStartCB _cbStart;
|
HTTPUpdateStartCB _cbStart;
|
||||||
HTTPUpdateEndCB _cbEnd;
|
HTTPUpdateEndCB _cbEnd;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user