…生活與工作…個人的生活雜記….

ESP8266 OTA線上更新

使用 HTTP SERVER方式更新,只須連上網路即可。

需要一台web server

Arduino方面:

#include <ESP8266WiFi.h>
#include <ESP8266httpUpdate.h>
extern "C" {
    #include "user_interface.h"
    extern struct rst_info resetInfo;
}

//定義
#define ota_server "http://server.ip.or.dns/update.php"
#define FW_NAME "OTA-firmware"
#define FW_VERSION "1.0.0"



ESPhttpUpdate.rebootOnUpdate(false);
t_httpUpdate_return ret = ESPhttpUpdate.update(ota_server,FW_VERSION);
switch(ret) {
    case HTTP_UPDATE_FAILED:
        Serial.printf("[OTA]更新失敗 (%d): %s", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
        break;

    case HTTP_UPDATE_NO_UPDATES:
        Serial.println("[OTA]沒有發現新版本.");
        break;

    case HTTP_UPDATE_OK:
        Serial.println("[OTA]更新為最新版本完成."); 
        ESP.restart();
        break;
}

Web Server方面:

<?PHP

header('Content-type: text/plain; charset=utf8', true);

function check_header($name, $value = false) {
    if(!isset($_SERVER[$name])) {
        return false;
    }
    if($value && $_SERVER[$name] != $value) {
        return false;
    }
        return true;
}

function sendFile($path) {
    header($_SERVER["SERVER_PROTOCOL"].' 200 OK', true, 200);
    header('Content-Type: application/octet-stream', true);
    header('Content-Disposition: attachment; filename='.basename($path));
    header('Content-Length: '.filesize($path), true);
    header('x-MD5: '.md5_file($path), true);
    readfile($path);
}

if(!check_header('HTTP_USER_AGENT', 'ESP8266-http-Update')) {
    header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden', true, 403);
    echo "only for ESP8266 updater!\n";
    exit();
}

if(!check_header('HTTP_X_ESP8266_STA_MAC') ||
   !check_header('HTTP_X_ESP8266_AP_MAC') ||
   !check_header('HTTP_X_ESP8266_FREE_SPACE') ||
   !check_header('HTTP_X_ESP8266_SKETCH_SIZE') ||
   !check_header('HTTP_X_ESP8266_SKETCH_MD5') ||
   !check_header('HTTP_X_ESP8266_CHIP_SIZE') ||
   !check_header('HTTP_X_ESP8266_SDK_VERSION')) {
    header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden', true, 403);
    echo "only for ESP8266 updater! (header)\n";
    exit();
}

$db = array(
            "MAC_ADDRESS" => "fw_name.ino"
      );

if(!isset($db[$_SERVER['HTTP_X_ESP8266_STA_MAC']])) {
    header($_SERVER["SERVER_PROTOCOL"].' 500 ESP MAC not configured for updates', true, 500);
}

$localBinary = "./".$db[$_SERVER['HTTP_X_ESP8266_STA_MAC']].".bin";

if((!check_header('HTTP_X_ESP8266_SDK_VERSION') && 
    $db[$_SERVER['HTTP_X_ESP8266_STA_MAC']] != 
    $_SERVER['HTTP_X_ESP8266_VERSION']) || 
    $_SERVER["HTTP_X_ESP8266_SKETCH_MD5"] != 
    md5_file($localBinary)) {
        sendFile($localBinary);
    } else {
        header($_SERVER["SERVER_PROTOCOL"].' 304 Not Modified', true, 304);
}
?>