mirror of
				https://github.com/esp8266/Arduino.git
				synced 2025-11-03 14:33:37 +03:00 
			
		
		
		
	
							
								
								
									
										43
									
								
								cores/esp8266/MD5Builder.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								cores/esp8266/MD5Builder.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					#include "Arduino.h"
 | 
				
			||||||
 | 
					#include "md5.h"
 | 
				
			||||||
 | 
					#include "MD5Builder.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define hex_char_to_byte(c) (((c)>='a'&&(c)<='f')?((c)-87):((c)>='A'&&(c)<='F')?((c)-55):((c)>='0'&&(c)<='9')?((c)-48):0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MD5Builder::begin(void){
 | 
				
			||||||
 | 
					  memset(_buf, 0x00, 16);
 | 
				
			||||||
 | 
					  MD5Init(&_ctx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MD5Builder::add(uint8_t * data, uint16_t len){
 | 
				
			||||||
 | 
					  MD5Update(&_ctx, data, len);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MD5Builder::addHexString(const char * data){
 | 
				
			||||||
 | 
					  uint16_t i, len = strlen(data);
 | 
				
			||||||
 | 
					  uint8_t * tmp = (uint8_t*)malloc(len/2);
 | 
				
			||||||
 | 
					  if(tmp == NULL)
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  for(i=0; i<len; i+=2) tmp[i/2] = (hex_char_to_byte(data[i]) & 0x0F) << 4 | (hex_char_to_byte(data[i+1]) & 0x0F);
 | 
				
			||||||
 | 
					  add(tmp, len/2);
 | 
				
			||||||
 | 
					  free(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MD5Builder::calculate(void){
 | 
				
			||||||
 | 
					  MD5Final(_buf, &_ctx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MD5Builder::getBytes(uint8_t * output){
 | 
				
			||||||
 | 
					  memcpy(output, _buf, 16);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MD5Builder::getChars(char * output){
 | 
				
			||||||
 | 
					  for(uint8_t i = 0; i < 16; i++)
 | 
				
			||||||
 | 
					    sprintf(output + (i * 2), "%02x", _buf[i]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String MD5Builder::toString(void){
 | 
				
			||||||
 | 
					  char out[32];
 | 
				
			||||||
 | 
					  getChars(out);
 | 
				
			||||||
 | 
					  return String(out);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										47
									
								
								cores/esp8266/MD5Builder.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								cores/esp8266/MD5Builder.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					/* 
 | 
				
			||||||
 | 
					  md5.h - exposed md5 ROM functions for esp8266
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Copyright (c) 2015 Hristo Gochkov. All rights reserved.
 | 
				
			||||||
 | 
					  This file is part of the esp8266 core for Arduino environment.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  This library is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					  modify it under the terms of the GNU Lesser General Public
 | 
				
			||||||
 | 
					  License as published by the Free Software Foundation; either
 | 
				
			||||||
 | 
					  version 2.1 of the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This library is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
				
			||||||
 | 
					  Lesser General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You should have received a copy of the GNU Lesser General Public
 | 
				
			||||||
 | 
					  License along with this library; if not, write to the Free Software
 | 
				
			||||||
 | 
					  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					#ifndef __ESP8266_MD5_BUILDER__
 | 
				
			||||||
 | 
					#define __ESP8266_MD5_BUILDER__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "Arduino.h"
 | 
				
			||||||
 | 
					#include "md5.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MD5Builder {
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					    md5_context_t _ctx;
 | 
				
			||||||
 | 
					    uint8_t _buf[16];
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    void begin(void);
 | 
				
			||||||
 | 
					    void add(uint8_t * data, uint16_t len);
 | 
				
			||||||
 | 
					    void add(const char * data){ add((uint8_t*)data, strlen(data)); }
 | 
				
			||||||
 | 
					    void add(char * data){ add((const char*)data); }
 | 
				
			||||||
 | 
					    void add(String data){ add(data.c_str()); }
 | 
				
			||||||
 | 
					    void addHexString(const char * data);
 | 
				
			||||||
 | 
					    void addHexString(char * data){ addHexString((const char*)data); }
 | 
				
			||||||
 | 
					    void addHexString(String data){ addHexString(data.c_str()); }
 | 
				
			||||||
 | 
					    void calculate(void);
 | 
				
			||||||
 | 
					    void getBytes(uint8_t * output);
 | 
				
			||||||
 | 
					    void getChars(char * output);
 | 
				
			||||||
 | 
					    String toString(void);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@@ -32,6 +32,7 @@ void UpdaterClass::_reset() {
 | 
				
			|||||||
  _currentAddress = 0;
 | 
					  _currentAddress = 0;
 | 
				
			||||||
  _size = 0;
 | 
					  _size = 0;
 | 
				
			||||||
  _command = U_FLASH;
 | 
					  _command = U_FLASH;
 | 
				
			||||||
 | 
					  _target_md5 = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool UpdaterClass::begin(size_t size, int command) {
 | 
					bool UpdaterClass::begin(size_t size, int command) {
 | 
				
			||||||
@@ -97,9 +98,16 @@ bool UpdaterClass::begin(size_t size, int command) {
 | 
				
			|||||||
  _buffer = new uint8_t[FLASH_SECTOR_SIZE];
 | 
					  _buffer = new uint8_t[FLASH_SECTOR_SIZE];
 | 
				
			||||||
  _command = command;
 | 
					  _command = command;
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 | 
					  _target_md5 = new char[64];
 | 
				
			||||||
 | 
					  _md5.begin();
 | 
				
			||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void UpdaterClass::setMD5(const char * expected_md5){
 | 
				
			||||||
 | 
					  if(strlen(expected_md5) != 32) return;
 | 
				
			||||||
 | 
					  strcpy(_target_md5, expected_md5);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool UpdaterClass::end(bool evenIfRemaining){
 | 
					bool UpdaterClass::end(bool evenIfRemaining){
 | 
				
			||||||
  if(_size == 0){
 | 
					  if(_size == 0){
 | 
				
			||||||
#ifdef DEBUG_UPDATER
 | 
					#ifdef DEBUG_UPDATER
 | 
				
			||||||
@@ -124,6 +132,20 @@ bool UpdaterClass::end(bool evenIfRemaining){
 | 
				
			|||||||
    _size = progress();
 | 
					    _size = progress();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 | 
					  _md5.calculate();
 | 
				
			||||||
 | 
					  if(_target_md5 && strlen(_target_md5) == 32){
 | 
				
			||||||
 | 
					    if(strcmp(_target_md5, _md5.toString().c_str()) != 0){
 | 
				
			||||||
 | 
					      _error = UPDATE_ERROR_MD5;
 | 
				
			||||||
 | 
					#ifdef DEBUG_UPDATER
 | 
				
			||||||
 | 
					      DEBUG_UPDATER.printf("MD5 Failed: expected:%s, calculated:%s\n", _target_md5, _md5.toString().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#ifdef DEBUG_UPDATER
 | 
				
			||||||
 | 
					    else DEBUG_UPDATER.printf("MD5 Success: %s\n", _md5.toString().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
  if (_command == U_FLASH) {
 | 
					  if (_command == U_FLASH) {
 | 
				
			||||||
    eboot_command ebcmd;
 | 
					    eboot_command ebcmd;
 | 
				
			||||||
    ebcmd.action = ACTION_COPY_RAW;
 | 
					    ebcmd.action = ACTION_COPY_RAW;
 | 
				
			||||||
@@ -157,6 +179,7 @@ bool UpdaterClass::_writeBuffer(){
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  _md5.add(_buffer, _bufferLen);
 | 
				
			||||||
  _currentAddress += _bufferLen;
 | 
					  _currentAddress += _bufferLen;
 | 
				
			||||||
  _bufferLen = 0;
 | 
					  _bufferLen = 0;
 | 
				
			||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
@@ -232,6 +255,8 @@ void UpdaterClass::printError(Stream &out){
 | 
				
			|||||||
    out.println("Bad Size Given");
 | 
					    out.println("Bad Size Given");
 | 
				
			||||||
  } else if(_error == UPDATE_ERROR_STREAM){
 | 
					  } else if(_error == UPDATE_ERROR_STREAM){
 | 
				
			||||||
    out.println("Stream Read Timeout");
 | 
					    out.println("Stream Read Timeout");
 | 
				
			||||||
 | 
					  } else if(_error == UPDATE_ERROR_MD5){
 | 
				
			||||||
 | 
					    out.println("MD5 Check Failed");
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    out.println("UNKNOWN");
 | 
					    out.println("UNKNOWN");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "Arduino.h"
 | 
					#include "Arduino.h"
 | 
				
			||||||
#include "flash_utils.h"
 | 
					#include "flash_utils.h"
 | 
				
			||||||
 | 
					#include "MD5Builder.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define UPDATE_ERROR_OK     0
 | 
					#define UPDATE_ERROR_OK     0
 | 
				
			||||||
#define UPDATE_ERROR_WRITE  1
 | 
					#define UPDATE_ERROR_WRITE  1
 | 
				
			||||||
@@ -10,11 +11,12 @@
 | 
				
			|||||||
#define UPDATE_ERROR_SPACE  3
 | 
					#define UPDATE_ERROR_SPACE  3
 | 
				
			||||||
#define UPDATE_ERROR_SIZE   4
 | 
					#define UPDATE_ERROR_SIZE   4
 | 
				
			||||||
#define UPDATE_ERROR_STREAM 5
 | 
					#define UPDATE_ERROR_STREAM 5
 | 
				
			||||||
 | 
					#define UPDATE_ERROR_MD5    6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define U_FLASH   0
 | 
					#define U_FLASH   0
 | 
				
			||||||
#define U_SPIFFS  100
 | 
					#define U_SPIFFS  100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//#define DEBUG_UPDATER Serial1
 | 
					//#define DEBUG_UPDATER Serial
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UpdaterClass {
 | 
					class UpdaterClass {
 | 
				
			||||||
  public:
 | 
					  public:
 | 
				
			||||||
@@ -57,6 +59,21 @@ class UpdaterClass {
 | 
				
			|||||||
    */
 | 
					    */
 | 
				
			||||||
    void printError(Stream &out);
 | 
					    void printError(Stream &out);
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					      sets the expected MD5 for the firmware (hexString)
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    void setMD5(const char * expected_md5);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					      returns the MD5 String of the sucessfully ended firmware
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    String md5String(void){ return _md5.toString(); }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					      populated the result with the md5 bytes of the sucessfully ended firmware
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    void md5(uint8_t * result){ return _md5.getBytes(result); }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
    //Helpers
 | 
					    //Helpers
 | 
				
			||||||
    uint8_t getError(){ return _error; }
 | 
					    uint8_t getError(){ return _error; }
 | 
				
			||||||
    void clearError(){ _error = UPDATE_ERROR_OK; }
 | 
					    void clearError(){ _error = UPDATE_ERROR_OK; }
 | 
				
			||||||
@@ -103,7 +120,7 @@ class UpdaterClass {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        if(remaining() == 0)
 | 
					        if(remaining() == 0)
 | 
				
			||||||
          return written;
 | 
					          return written;
 | 
				
			||||||
        yield();
 | 
					        delay(1);
 | 
				
			||||||
        available = data.available();
 | 
					        available = data.available();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return written;
 | 
					      return written;
 | 
				
			||||||
@@ -120,6 +137,9 @@ class UpdaterClass {
 | 
				
			|||||||
    uint32_t _startAddress;
 | 
					    uint32_t _startAddress;
 | 
				
			||||||
    uint32_t _currentAddress;
 | 
					    uint32_t _currentAddress;
 | 
				
			||||||
    uint32_t _command;
 | 
					    uint32_t _command;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    char *_target_md5;
 | 
				
			||||||
 | 
					    MD5Builder _md5;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern UpdaterClass Update;
 | 
					extern UpdaterClass Update;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										44
									
								
								cores/esp8266/md5.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								cores/esp8266/md5.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					/* 
 | 
				
			||||||
 | 
					  md5.h - exposed md5 ROM functions for esp8266
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Copyright (c) 2015 Hristo Gochkov. All rights reserved.
 | 
				
			||||||
 | 
					  This file is part of the esp8266 core for Arduino environment.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  original C source from https://github.com/morrissinger/ESP8266-Websocket/raw/master/MD5.h
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  This library is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					  modify it under the terms of the GNU Lesser General Public
 | 
				
			||||||
 | 
					  License as published by the Free Software Foundation; either
 | 
				
			||||||
 | 
					  version 2.1 of the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This library is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
				
			||||||
 | 
					  Lesser General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You should have received a copy of the GNU Lesser General Public
 | 
				
			||||||
 | 
					  License along with this library; if not, write to the Free Software
 | 
				
			||||||
 | 
					  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					#ifndef __ESP8266_MD5__
 | 
				
			||||||
 | 
					#define __ESP8266_MD5__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					  uint32_t state[4];
 | 
				
			||||||
 | 
					  uint32_t count[2];
 | 
				
			||||||
 | 
					  uint8_t buffer[64];
 | 
				
			||||||
 | 
					} md5_context_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern void MD5Init (md5_context_t *);
 | 
				
			||||||
 | 
					extern void MD5Update (md5_context_t *, uint8_t *, uint16_t);
 | 
				
			||||||
 | 
					extern void MD5Final (uint8_t [16], md5_context_t *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					} // extern "C"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@@ -2,14 +2,26 @@
 | 
				
			|||||||
#include <ESP8266mDNS.h>
 | 
					#include <ESP8266mDNS.h>
 | 
				
			||||||
#include <WiFiUdp.h>
 | 
					#include <WiFiUdp.h>
 | 
				
			||||||
#include "ArduinoOTA.h"
 | 
					#include "ArduinoOTA.h"
 | 
				
			||||||
 | 
					#include "MD5Builder.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ArduinoOTA::ArduinoOTA(const char *mdns_host_prefix, int port, bool serial_debug)
 | 
					//#define OTA_DEBUG 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define U_AUTH 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ArduinoOTAClass::ArduinoOTAClass()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    _port = port;
 | 
					 | 
				
			||||||
    _mdns_host = new String(mdns_host_prefix);
 | 
					 | 
				
			||||||
    *_mdns_host += String(ESP.getChipId(), HEX);
 | 
					 | 
				
			||||||
    _udp_ota = new WiFiUDP();
 | 
					    _udp_ota = new WiFiUDP();
 | 
				
			||||||
    _serial_debug = serial_debug;
 | 
					    _password = 0;
 | 
				
			||||||
 | 
					    _hostname = 0;
 | 
				
			||||||
 | 
					    _port = 0;
 | 
				
			||||||
 | 
					    _nonce = 0;
 | 
				
			||||||
 | 
					    _state = OTA_IDLE;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    _size = 0;
 | 
				
			||||||
 | 
					    _cmd = 0;
 | 
				
			||||||
 | 
					    _ota_port = 0;
 | 
				
			||||||
 | 
					    _ota_ip = (uint32_t)0;
 | 
				
			||||||
 | 
					    _md5 = new char[33];
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    _start_callback    = NULL;
 | 
					    _start_callback    = NULL;
 | 
				
			||||||
    _end_callback      = NULL;
 | 
					    _end_callback      = NULL;
 | 
				
			||||||
@@ -17,104 +29,227 @@ ArduinoOTA::ArduinoOTA(const char *mdns_host_prefix, int port, bool serial_debug
 | 
				
			|||||||
    _error_callback    = NULL;
 | 
					    _error_callback    = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ArduinoOTA::onStart(OTA_CALLBACK(fn)){
 | 
					void ArduinoOTAClass::onStart(OTA_CALLBACK(fn)){
 | 
				
			||||||
    _start_callback = fn;
 | 
					    _start_callback = fn;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ArduinoOTA::onEnd(OTA_CALLBACK(fn)){
 | 
					void ArduinoOTAClass::onEnd(OTA_CALLBACK(fn)){
 | 
				
			||||||
    _end_callback = fn;
 | 
					    _end_callback = fn;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ArduinoOTA::onProgress(OTA_CALLBACK_PROGRESS(fn)){
 | 
					void ArduinoOTAClass::onProgress(OTA_CALLBACK_PROGRESS(fn)){
 | 
				
			||||||
    _progress_callback = fn;
 | 
					    _progress_callback = fn;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ArduinoOTA::onError(OTA_CALLBACK(fn)){
 | 
					void ArduinoOTAClass::onError(OTA_CALLBACK_ERROR(fn)){
 | 
				
			||||||
    _error_callback = fn;
 | 
					    _error_callback = fn;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ArduinoOTA::~ArduinoOTA(){
 | 
					ArduinoOTAClass::~ArduinoOTAClass(){
 | 
				
			||||||
    delete _udp_ota;
 | 
					    delete _udp_ota;
 | 
				
			||||||
    delete _mdns_host;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ArduinoOTA::setup() {
 | 
					void ArduinoOTAClass::setPort(uint16_t port){
 | 
				
			||||||
  _udp_ota->begin(_port);
 | 
					  if(!_initialized && !_port && port){
 | 
				
			||||||
  if (_mdns_host) {
 | 
					    _port = port;
 | 
				
			||||||
    if (_serial_debug)
 | 
					 | 
				
			||||||
      Serial.printf("OTA server at: %s:%u\n",
 | 
					 | 
				
			||||||
                    _mdns_host->c_str(),
 | 
					 | 
				
			||||||
                    _port);
 | 
					 | 
				
			||||||
    MDNS.begin(_mdns_host->c_str());
 | 
					 | 
				
			||||||
    MDNS.addService("arduino", "tcp", _port);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ArduinoOTA::handle() {
 | 
					void ArduinoOTAClass::setHostname(const char * hostname){
 | 
				
			||||||
 | 
					  if(!_initialized && !_hostname && hostname){
 | 
				
			||||||
 | 
					    _hostname = new char[strlen(hostname)];
 | 
				
			||||||
 | 
					    sprintf(_hostname, "%s", hostname);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ArduinoOTAClass::setPassword(const char * password){
 | 
				
			||||||
 | 
					  if(!_initialized && !_password && password){
 | 
				
			||||||
 | 
					    _password = new char[strlen(password)];
 | 
				
			||||||
 | 
					    sprintf(_password, "%s", password);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ArduinoOTAClass::begin() {
 | 
				
			||||||
 | 
					  if(_initialized)
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  _initialized = true;
 | 
				
			||||||
 | 
					  if(!_hostname){
 | 
				
			||||||
 | 
					    _hostname = new char[15];
 | 
				
			||||||
 | 
					    sprintf(_hostname, "esp8266-%02x", ESP.getChipId());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if(!_port)
 | 
				
			||||||
 | 
					    _port = 8266;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  _udp_ota->begin(_port);
 | 
				
			||||||
 | 
					  MDNS.begin(_hostname);
 | 
				
			||||||
 | 
					  if(_password){
 | 
				
			||||||
 | 
					    _nonce = new char[33];
 | 
				
			||||||
 | 
					    MDNS.enableArduino(_port, true);
 | 
				
			||||||
 | 
					  } else 
 | 
				
			||||||
 | 
					    MDNS.enableArduino(_port);
 | 
				
			||||||
 | 
					  _state = OTA_IDLE;
 | 
				
			||||||
 | 
					#if OTA_DEBUG
 | 
				
			||||||
 | 
					  Serial.printf("OTA server at: %s.local:%u\n", _hostname, _port);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ArduinoOTAClass::_runUpdate(){
 | 
				
			||||||
 | 
					  if(!Update.begin(_size, _cmd)){
 | 
				
			||||||
 | 
					#if OTA_DEBUG
 | 
				
			||||||
 | 
					    Serial.println("Update Begin Error");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    if (_error_callback) _error_callback(OTA_BEGIN_ERROR);
 | 
				
			||||||
 | 
					    _udp_ota->begin(_port);
 | 
				
			||||||
 | 
					    _state = OTA_IDLE;
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  Update.setMD5(_md5);
 | 
				
			||||||
 | 
					  WiFiUDP::stopAll();
 | 
				
			||||||
 | 
					  WiFiClient::stopAll();
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (_start_callback) _start_callback();
 | 
				
			||||||
 | 
					  if (_progress_callback) _progress_callback(0, _size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  WiFiClient client;
 | 
				
			||||||
 | 
					  if (!client.connect(_ota_ip, _ota_port)) {
 | 
				
			||||||
 | 
					#if OTA_DEBUG
 | 
				
			||||||
 | 
					    Serial.printf("Connect Failed\n");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    _udp_ota->begin(_port);
 | 
				
			||||||
 | 
					    if (_error_callback) _error_callback(OTA_CONNECT_ERROR);
 | 
				
			||||||
 | 
					    _state = OTA_IDLE;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint32_t written, total = 0;
 | 
				
			||||||
 | 
					  while(!Update.isFinished() && client.connected()){
 | 
				
			||||||
 | 
					    int waited = 1000;
 | 
				
			||||||
 | 
					    while(!client.available() && waited--)
 | 
				
			||||||
 | 
					      delay(1);
 | 
				
			||||||
 | 
					    if(!waited){
 | 
				
			||||||
 | 
					#if OTA_DEBUG
 | 
				
			||||||
 | 
					      Serial.printf("Recieve Failed\n");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      _udp_ota->begin(_port);
 | 
				
			||||||
 | 
					      if (_error_callback) _error_callback(OTA_RECIEVE_ERROR);
 | 
				
			||||||
 | 
					      _state = OTA_IDLE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    written = Update.write(client); 
 | 
				
			||||||
 | 
					    if(written > 0){
 | 
				
			||||||
 | 
					      client.print(written, DEC);
 | 
				
			||||||
 | 
					      total += written;
 | 
				
			||||||
 | 
					      if(_progress_callback) _progress_callback(total, _size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if(Update.end()){
 | 
				
			||||||
 | 
					    client.print("OK");
 | 
				
			||||||
 | 
					    client.stop();
 | 
				
			||||||
 | 
					    delay(10);
 | 
				
			||||||
 | 
					#if OTA_DEBUG
 | 
				
			||||||
 | 
					    Serial.printf("Update Success\nRebooting...\n");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    if(_end_callback) _end_callback();
 | 
				
			||||||
 | 
					    ESP.restart();
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    _udp_ota->begin(_port);
 | 
				
			||||||
 | 
					    if (_error_callback) _error_callback(OTA_END_ERROR);
 | 
				
			||||||
 | 
					    Update.printError(client);
 | 
				
			||||||
 | 
					#if OTA_DEBUG
 | 
				
			||||||
 | 
					    Update.printError(Serial);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    _state = OTA_IDLE;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ArduinoOTAClass::handle() {
 | 
				
			||||||
  if (!*_udp_ota) {
 | 
					  if (!*_udp_ota) {
 | 
				
			||||||
    _udp_ota->begin(_port); 
 | 
					    _udp_ota->begin(_port); 
 | 
				
			||||||
        if (_serial_debug) {
 | 
					#if OTA_DEBUG
 | 
				
			||||||
    Serial.println("OTA restarted"); 
 | 
					    Serial.println("OTA restarted"); 
 | 
				
			||||||
        }
 | 
					#endif
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!_udp_ota->parsePacket()) return;
 | 
					  if (!_udp_ota->parsePacket()) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  IPAddress remote = _udp_ota->remoteIP();
 | 
					  if(_state == OTA_IDLE){
 | 
				
			||||||
    int cmd = _udp_ota->parseInt();
 | 
					    int cmd = _udp_ota->parseInt();
 | 
				
			||||||
  int port = _udp_ota->parseInt();
 | 
					    if(cmd != U_FLASH && cmd != U_SPIFFS)
 | 
				
			||||||
  int size = _udp_ota->parseInt();
 | 
					      return;
 | 
				
			||||||
 | 
					    _ota_ip = _udp_ota->remoteIP();
 | 
				
			||||||
 | 
					    _cmd  = cmd;
 | 
				
			||||||
 | 
					    _ota_port = _udp_ota->parseInt();
 | 
				
			||||||
 | 
					    _size = _udp_ota->parseInt();
 | 
				
			||||||
 | 
					    _udp_ota->read();
 | 
				
			||||||
 | 
					    sprintf(_md5, "%s", _udp_ota->readStringUntil('\n').c_str());
 | 
				
			||||||
 | 
					    if(strlen(_md5) != 32)
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (_serial_debug){
 | 
					#if OTA_DEBUG
 | 
				
			||||||
    Serial.print("Update Start: ip:");
 | 
					    Serial.print("Update Start: ip:");
 | 
				
			||||||
      Serial.print(remote);
 | 
					    Serial.print(_ota_ip);
 | 
				
			||||||
      Serial.printf(", port:%d, size:%d\n", port, size);
 | 
					    Serial.printf(", port:%d, size:%d, md5:%s\n", _ota_port, _size, _md5);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    _udp_ota->beginPacket(_ota_ip, _udp_ota->remotePort());
 | 
				
			||||||
 | 
					    if(_password){
 | 
				
			||||||
 | 
					      MD5Builder nonce_md5;
 | 
				
			||||||
 | 
					      nonce_md5.begin();
 | 
				
			||||||
 | 
					      nonce_md5.add(String(micros()));
 | 
				
			||||||
 | 
					      nonce_md5.calculate();
 | 
				
			||||||
 | 
					      nonce_md5.getChars(_nonce);
 | 
				
			||||||
 | 
					      _udp_ota->printf("AUTH %s", _nonce);
 | 
				
			||||||
 | 
					      _udp_ota->endPacket();
 | 
				
			||||||
 | 
					      _state = OTA_WAITAUTH;
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      _udp_ota->print("OK");
 | 
				
			||||||
 | 
					      _udp_ota->endPacket();
 | 
				
			||||||
 | 
					      _state = OTA_RUNUPDATE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  } else if(_state == OTA_WAITAUTH){
 | 
				
			||||||
  WiFiUDP::stopAll();
 | 
					    int cmd = _udp_ota->parseInt();
 | 
				
			||||||
 | 
					    if(cmd != U_AUTH){
 | 
				
			||||||
  if(!Update.begin(size, cmd)){
 | 
					      _state = OTA_IDLE;
 | 
				
			||||||
    if (_serial_debug)
 | 
					 | 
				
			||||||
        Serial.println("Update Begin Error");
 | 
					 | 
				
			||||||
    if (_error_callback) _error_callback();
 | 
					 | 
				
			||||||
    _udp_ota->begin(_port);
 | 
					 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  if (_start_callback) _start_callback();
 | 
					    _udp_ota->read();
 | 
				
			||||||
  if (_progress_callback) _progress_callback(0, size);
 | 
					    String cnonce = _udp_ota->readStringUntil(' ');
 | 
				
			||||||
 | 
					    String response = _udp_ota->readStringUntil('\n');
 | 
				
			||||||
  WiFiClient client;
 | 
					    if(cnonce.length() != 32 || response.length() != 32){
 | 
				
			||||||
  if (!client.connect(remote, port)) {
 | 
					      _state = OTA_IDLE;
 | 
				
			||||||
    if (_serial_debug)
 | 
					      return;
 | 
				
			||||||
        Serial.printf("Connect Failed\n");
 | 
					 | 
				
			||||||
    _udp_ota->begin(_port);
 | 
					 | 
				
			||||||
    if (_error_callback) _error_callback();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
  uint32_t written;
 | 
					    MD5Builder _passmd5;
 | 
				
			||||||
  while(!Update.isFinished() && client.connected()){
 | 
					    _passmd5.begin();
 | 
				
			||||||
    // TODO(mangelajo): enhance the Update.write(client) to 
 | 
					    _passmd5.add(_password);
 | 
				
			||||||
    // accept a progress callback
 | 
					    _passmd5.calculate();
 | 
				
			||||||
    written = Update.write(client); 
 | 
					    String passmd5 = _passmd5.toString();
 | 
				
			||||||
    if(written > 0) client.print(written, DEC);
 | 
					 | 
				
			||||||
    if(_progress_callback) _progress_callback(written, size);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Serial.setDebugOutput(false);
 | 
					    String challenge = passmd5 + ":" + String(_nonce) + ":" + cnonce;
 | 
				
			||||||
 | 
					    MD5Builder _challengemd5;
 | 
				
			||||||
 | 
					    _challengemd5.begin();
 | 
				
			||||||
 | 
					    _challengemd5.add(challenge);
 | 
				
			||||||
 | 
					    _challengemd5.calculate();
 | 
				
			||||||
 | 
					    String result = _challengemd5.toString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if(Update.end()){
 | 
					    if(result.equals(response)){
 | 
				
			||||||
    client.println("OK");
 | 
					      _udp_ota->beginPacket(_ota_ip, _udp_ota->remotePort());
 | 
				
			||||||
    if (_serial_debug)
 | 
					      _udp_ota->print("OK");
 | 
				
			||||||
        Serial.printf("Update Success\nRebooting...\n");
 | 
					      _udp_ota->endPacket();
 | 
				
			||||||
    if(_end_callback) _end_callback();
 | 
					      _state = OTA_RUNUPDATE;
 | 
				
			||||||
    ESP.restart();
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
    // Update failed: listen UDP again, callback and print
 | 
					      _udp_ota->beginPacket(_ota_ip, _udp_ota->remotePort());
 | 
				
			||||||
    _udp_ota->begin(_port);
 | 
					      _udp_ota->print("Authentication Failed");
 | 
				
			||||||
    if (_error_callback) _error_callback();
 | 
					      _udp_ota->endPacket();
 | 
				
			||||||
    Update.printError(client);
 | 
					      if (_error_callback) _error_callback(OTA_AUTH_ERROR);
 | 
				
			||||||
    if (_serial_debug)
 | 
					      _state = OTA_IDLE;
 | 
				
			||||||
        Update.printError(Serial);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if(_state == OTA_RUNUPDATE)
 | 
				
			||||||
 | 
					    _runUpdate();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ArduinoOTAClass ArduinoOTA;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,31 +5,58 @@ class WiFiUDP;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define OTA_CALLBACK(callback) void (*callback)()
 | 
					#define OTA_CALLBACK(callback) void (*callback)()
 | 
				
			||||||
#define OTA_CALLBACK_PROGRESS(callback)  void (*callback)(unsigned int, unsigned int)
 | 
					#define OTA_CALLBACK_PROGRESS(callback)  void (*callback)(unsigned int, unsigned int)
 | 
				
			||||||
 | 
					#define OTA_CALLBACK_ERROR(callback)  void (*callback)(ota_error_t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ArduinoOTA
 | 
					typedef enum {
 | 
				
			||||||
 | 
					  OTA_IDLE,
 | 
				
			||||||
 | 
					  OTA_WAITAUTH,
 | 
				
			||||||
 | 
					  OTA_RUNUPDATE
 | 
				
			||||||
 | 
					} ota_state_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum {
 | 
				
			||||||
 | 
					  OTA_AUTH_ERROR,
 | 
				
			||||||
 | 
					  OTA_BEGIN_ERROR,
 | 
				
			||||||
 | 
					  OTA_CONNECT_ERROR,
 | 
				
			||||||
 | 
					  OTA_RECIEVE_ERROR,
 | 
				
			||||||
 | 
					  OTA_END_ERROR
 | 
				
			||||||
 | 
					} ota_error_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ArduinoOTAClass
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
    int _port;
 | 
					    int _port;
 | 
				
			||||||
    String* _mdns_host;
 | 
					    char *_password;
 | 
				
			||||||
 | 
					    char * _hostname;
 | 
				
			||||||
 | 
					    char * _nonce;
 | 
				
			||||||
    WiFiUDP* _udp_ota;
 | 
					    WiFiUDP* _udp_ota;
 | 
				
			||||||
    bool _serial_debug;
 | 
					    bool _initialized;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    ota_state_t _state;
 | 
				
			||||||
 | 
					    int _size, _cmd, _ota_port;
 | 
				
			||||||
 | 
					    IPAddress _ota_ip;
 | 
				
			||||||
 | 
					    char * _md5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    OTA_CALLBACK(_start_callback);
 | 
					    OTA_CALLBACK(_start_callback);
 | 
				
			||||||
    OTA_CALLBACK(_end_callback);
 | 
					    OTA_CALLBACK(_end_callback);
 | 
				
			||||||
    OTA_CALLBACK(_error_callback);
 | 
					    OTA_CALLBACK_ERROR(_error_callback);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    OTA_CALLBACK_PROGRESS(_progress_callback);
 | 
					    OTA_CALLBACK_PROGRESS(_progress_callback);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    void _runUpdate(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public:
 | 
					  public:
 | 
				
			||||||
        ArduinoOTA(const char *mdns_host="ESP8266-OTA-",
 | 
					    ArduinoOTAClass();
 | 
				
			||||||
                   int port=8266,
 | 
					    ~ArduinoOTAClass();
 | 
				
			||||||
                   bool serial_debug=true);
 | 
					    void setPort(uint16_t port);
 | 
				
			||||||
        ~ArduinoOTA();
 | 
					    void setHostname(const char *hostname);
 | 
				
			||||||
        void setup();
 | 
					    void setPassword(const char *password);
 | 
				
			||||||
        void handle();
 | 
					 | 
				
			||||||
    void onStart(OTA_CALLBACK(fn));
 | 
					    void onStart(OTA_CALLBACK(fn));
 | 
				
			||||||
    void onEnd(OTA_CALLBACK(fn));
 | 
					    void onEnd(OTA_CALLBACK(fn));
 | 
				
			||||||
    void onProgress(OTA_CALLBACK_PROGRESS(fn));
 | 
					    void onProgress(OTA_CALLBACK_PROGRESS(fn));
 | 
				
			||||||
        void onError(OTA_CALLBACK (fn));
 | 
					    void onError(OTA_CALLBACK_ERROR (fn));
 | 
				
			||||||
 | 
					    void begin();
 | 
				
			||||||
 | 
					    void handle();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern ArduinoOTAClass ArduinoOTA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* __ARDUINO_OTA_H */
 | 
					#endif /* __ARDUINO_OTA_H */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,26 +6,36 @@
 | 
				
			|||||||
const char* ssid = "...";
 | 
					const char* ssid = "...";
 | 
				
			||||||
const char* password = "...";
 | 
					const char* password = "...";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ArduinoOTA ota_server;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void setup() {
 | 
					void setup() {
 | 
				
			||||||
  Serial.begin(115200);
 | 
					  Serial.begin(115200);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  Serial.println("Booting");
 | 
					  Serial.println("Booting");
 | 
				
			||||||
  WiFi.mode(WIFI_STA);
 | 
					  WiFi.mode(WIFI_STA);
 | 
				
			||||||
 | 
					 | 
				
			||||||
   /* try the flash stored password first */
 | 
					 | 
				
			||||||
   WiFi.begin();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   while (WiFi.waitForConnectResult() != WL_CONNECTED){
 | 
					 | 
				
			||||||
  WiFi.begin(ssid, password);
 | 
					  WiFi.begin(ssid, password);
 | 
				
			||||||
     Serial.println("Retrying connection...");
 | 
					  while (WiFi.waitForConnectResult() != WL_CONNECTED){
 | 
				
			||||||
 | 
					     Serial.println("Connection Failed! Rebooting...");
 | 
				
			||||||
 | 
					     delay(5000);
 | 
				
			||||||
 | 
					     ESP.reset();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  ota_server.setup();
 | 
					  //ArduinoOTA.setPort(8266);//Defaults to 8266
 | 
				
			||||||
 | 
					  //ArduinoOTA.setHostname((const char *)"myesp8266");//Defaults to esp8266-[ChipID]
 | 
				
			||||||
 | 
					  //ArduinoOTA.setPassword((const char *)"123");//defaults to no authentication
 | 
				
			||||||
 | 
					  ArduinoOTA.onStart([]() { Serial.println("Start"); });
 | 
				
			||||||
 | 
					  ArduinoOTA.onEnd([]() { Serial.println("End"); });
 | 
				
			||||||
 | 
					  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
 | 
				
			||||||
 | 
					    Serial.printf("Progress: %u%%\n", (progress/(total/100)));
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  ArduinoOTA.onError([](ota_error_t error) {
 | 
				
			||||||
 | 
					    Serial.printf("Error[%u]: ", error);
 | 
				
			||||||
 | 
					    if(error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
 | 
				
			||||||
 | 
					    else if(error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
 | 
				
			||||||
 | 
					    else if(error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
 | 
				
			||||||
 | 
					    else if(error == OTA_RECIEVE_ERROR) Serial.println("Recieve Failed");
 | 
				
			||||||
 | 
					    else if(error == OTA_END_ERROR) Serial.println("End Failed");
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  ArduinoOTA.begin();
 | 
				
			||||||
  Serial.println("Ready");
 | 
					  Serial.println("Ready");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void loop() {
 | 
					void loop() {
 | 
				
			||||||
  ota_server.handle();
 | 
					  ArduinoOTA.handle();
 | 
				
			||||||
  yield();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,9 +5,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const char* ssid = "...";
 | 
					const char* ssid = "...";
 | 
				
			||||||
const char* password = "...";
 | 
					const char* password = "...";
 | 
				
			||||||
const char* host_prefix = "OTA-LEDS-";
 | 
					const char* host = "OTA-LEDS";
 | 
				
			||||||
 | 
					 | 
				
			||||||
ArduinoOTA ota_server(host_prefix, 8266, /* debug_serial= */ true);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
int led_pin = 13;
 | 
					int led_pin = 13;
 | 
				
			||||||
#define N_DIMMERS 3
 | 
					#define N_DIMMERS 3
 | 
				
			||||||
@@ -23,8 +21,7 @@ void setup() {
 | 
				
			|||||||
   Serial.println("Booting");
 | 
					   Serial.println("Booting");
 | 
				
			||||||
   WiFi.mode(WIFI_STA);
 | 
					   WiFi.mode(WIFI_STA);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   /* try the flash stored password first */
 | 
					   WiFi.begin(ssid, password);
 | 
				
			||||||
   WiFi.begin();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
   while (WiFi.waitForConnectResult() != WL_CONNECTED){
 | 
					   while (WiFi.waitForConnectResult() != WL_CONNECTED){
 | 
				
			||||||
     WiFi.begin(ssid, password);
 | 
					     WiFi.begin(ssid, password);
 | 
				
			||||||
@@ -33,10 +30,6 @@ void setup() {
 | 
				
			|||||||
  /* switch off led */
 | 
					  /* switch off led */
 | 
				
			||||||
  digitalWrite(led_pin, HIGH);
 | 
					  digitalWrite(led_pin, HIGH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* setup the OTA server */
 | 
					 | 
				
			||||||
  ota_server.setup();
 | 
					 | 
				
			||||||
  Serial.println("Ready");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* configure dimmers, and OTA server events */
 | 
					  /* configure dimmers, and OTA server events */
 | 
				
			||||||
  analogWriteRange(1000);
 | 
					  analogWriteRange(1000);
 | 
				
			||||||
  analogWrite(led_pin,990);
 | 
					  analogWrite(led_pin,990);
 | 
				
			||||||
@@ -47,13 +40,14 @@ void setup() {
 | 
				
			|||||||
    analogWrite(dimmer_pin[i],50);
 | 
					    analogWrite(dimmer_pin[i],50);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ota_server.onStart([]() { // switch off all the PWMs during upgrade
 | 
					  ArduinoOTA.setHostname(host);
 | 
				
			||||||
 | 
					  ArduinoOTA.onStart([]() { // switch off all the PWMs during upgrade
 | 
				
			||||||
                        for(int i=0; i<N_DIMMERS;i++)
 | 
					                        for(int i=0; i<N_DIMMERS;i++)
 | 
				
			||||||
                          analogWrite(dimmer_pin[i], 0);
 | 
					                          analogWrite(dimmer_pin[i], 0);
 | 
				
			||||||
                          analogWrite(led_pin,0);
 | 
					                          analogWrite(led_pin,0);
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ota_server.onEnd([]() { // do a fancy thing with our board led at end
 | 
					  ArduinoOTA.onEnd([]() { // do a fancy thing with our board led at end
 | 
				
			||||||
                          for (int i=0;i<30;i++)
 | 
					                          for (int i=0;i<30;i++)
 | 
				
			||||||
                          {
 | 
					                          {
 | 
				
			||||||
                            analogWrite(led_pin,(i*100) % 1001);
 | 
					                            analogWrite(led_pin,(i*100) % 1001);
 | 
				
			||||||
@@ -61,11 +55,14 @@ void setup() {
 | 
				
			|||||||
                          }
 | 
					                          }
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   ota_server.onError([]() { ESP.restart(); });
 | 
					   ArduinoOTA.onError([](ota_error_t error) { ESP.restart(); });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   /* setup the OTA server */
 | 
				
			||||||
 | 
					   ArduinoOTA.begin();
 | 
				
			||||||
 | 
					   Serial.println("Ready");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void loop() {
 | 
					void loop() {
 | 
				
			||||||
  ota_server.handle();
 | 
					  ArduinoOTA.handle();
 | 
				
			||||||
  yield();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,7 +85,7 @@ static const IPAddress MDNS_MULTICAST_ADDR(224, 0, 0, 251);
 | 
				
			|||||||
static const int MDNS_MULTICAST_TTL = 1;
 | 
					static const int MDNS_MULTICAST_TTL = 1;
 | 
				
			||||||
static const int MDNS_PORT = 5353;
 | 
					static const int MDNS_PORT = 5353;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MDNSResponder::MDNSResponder() : _conn(0) { _services = 0; }
 | 
					MDNSResponder::MDNSResponder() : _conn(0) { _services = 0; _arduinoAuth = false; }
 | 
				
			||||||
MDNSResponder::~MDNSResponder() {}
 | 
					MDNSResponder::~MDNSResponder() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool MDNSResponder::begin(const char* domain){
 | 
					bool MDNSResponder::begin(const char* domain){
 | 
				
			||||||
@@ -101,8 +101,6 @@ bool MDNSResponder::begin(const char* domain){
 | 
				
			|||||||
    _hostName[i] = tolower(domain[i]);
 | 
					    _hostName[i] = tolower(domain[i]);
 | 
				
			||||||
  _hostName[n] = '\0';
 | 
					  _hostName[n] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  os_strcpy(_boardName, ARDUINO_BOARD);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Open the MDNS socket if it isn't already open.
 | 
					  // Open the MDNS socket if it isn't already open.
 | 
				
			||||||
  if (!_conn) {
 | 
					  if (!_conn) {
 | 
				
			||||||
    uint32_t ourIp = _getOurIp();
 | 
					    uint32_t ourIp = _getOurIp();
 | 
				
			||||||
@@ -372,7 +370,10 @@ void MDNSResponder::_parsePacket(){
 | 
				
			|||||||
  return _reply(responseMask, (serviceName), (protoName), servicePort);
 | 
					  return _reply(responseMask, (serviceName), (protoName), servicePort);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MDNSResponder::enableArduino(uint16_t port, bool auth){
 | 
				
			||||||
 | 
					  _arduinoAuth = auth;
 | 
				
			||||||
 | 
					  addService("arduino", "tcp", port);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint16_t port){
 | 
					void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint16_t port){
 | 
				
			||||||
  int i;
 | 
					  int i;
 | 
				
			||||||
@@ -439,24 +440,53 @@ void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint1
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // TXT Response
 | 
					  // TXT Response
 | 
				
			||||||
  if(replyMask & 0x4){
 | 
					  if(replyMask & 0x4){
 | 
				
			||||||
    if(replyMask & 0x8){//send the name
 | 
					    if(replyMask & 0x8){
 | 
				
			||||||
      uint8_t txtHead[2] = {0xC0, (uint8_t)(36 + serviceLen)};
 | 
					      uint8_t txtHead[10] = {
 | 
				
			||||||
      _conn->append(reinterpret_cast<const char*>(txtHead), 2);
 | 
					        0xC0, (uint8_t)(36 + serviceLen),//send the name
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint8_t boardNameLen = os_strlen(_boardName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint8_t txt[24] = {
 | 
					 | 
				
			||||||
        0x00, 0x10, //Type TXT
 | 
					        0x00, 0x10, //Type TXT
 | 
				
			||||||
        0x80, 0x01, //Class IN, with cache flush
 | 
					        0x80, 0x01, //Class IN, with cache flush
 | 
				
			||||||
        0x00, 0x00, 0x11, 0x94, //TTL 4500
 | 
					        0x00, 0x00, 0x11, 0x94, //TTL 4500
 | 
				
			||||||
      0x00, 0x0e, //DATA LEN
 | 
					 | 
				
			||||||
      (uint8_t)(6 + boardNameLen), //strlen(board=) + strlen(boardName)
 | 
					 | 
				
			||||||
      0x62, 0x6f, 0x61, 0x72, 0x64, 0x3d //board=
 | 
					 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    _conn->append(reinterpret_cast<const char*>(txt), 17);
 | 
					      _conn->append(reinterpret_cast<const char*>(txtHead), 10);
 | 
				
			||||||
    _conn->append(reinterpret_cast<const char*>(_boardName), boardNameLen);
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(strcmp(reinterpret_cast<const char*>("arduino"), service) == 0){
 | 
				
			||||||
 | 
					      //arduino
 | 
				
			||||||
 | 
					      //arduino service dependance should be removed and properties abstracted
 | 
				
			||||||
 | 
					      const char *tcpCheckExtra = "tcp_check=no";
 | 
				
			||||||
 | 
					      uint8_t tcpCheckExtraLen = os_strlen(tcpCheckExtra);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      const char *sshUploadExtra = "ssh_upload=no";
 | 
				
			||||||
 | 
					      uint8_t sshUploadExtraLen = os_strlen(sshUploadExtra);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      char boardName[64];
 | 
				
			||||||
 | 
					      const char *boardExtra = "board=";
 | 
				
			||||||
 | 
					      os_sprintf(boardName, "%s%s\0", boardExtra, ARDUINO_BOARD);
 | 
				
			||||||
 | 
					      uint8_t boardNameLen = os_strlen(boardName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      char authUpload[16];
 | 
				
			||||||
 | 
					      const char *authUploadExtra = "auth_upload=";
 | 
				
			||||||
 | 
					      os_sprintf(authUpload, "%s%s\0", authUploadExtra, reinterpret_cast<const char*>((_arduinoAuth)?"yes":"no"));
 | 
				
			||||||
 | 
					      uint8_t authUploadLen = os_strlen(authUpload);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					      uint16_t textDataLen = (1 + boardNameLen) + (1 + tcpCheckExtraLen) + (1 + sshUploadExtraLen) + (1 + authUploadLen);
 | 
				
			||||||
 | 
					      uint8_t txt[2] = {(uint8_t)(textDataLen >> 8), (uint8_t)(textDataLen)}; //DATA LEN
 | 
				
			||||||
 | 
					      _conn->append(reinterpret_cast<const char*>(txt), 2);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      _conn->append(reinterpret_cast<const char*>(&boardNameLen), 1);
 | 
				
			||||||
 | 
					      _conn->append(reinterpret_cast<const char*>(boardName), boardNameLen);
 | 
				
			||||||
 | 
					      _conn->append(reinterpret_cast<const char*>(&authUploadLen), 1);
 | 
				
			||||||
 | 
					      _conn->append(reinterpret_cast<const char*>(authUpload), authUploadLen);
 | 
				
			||||||
 | 
					      _conn->append(reinterpret_cast<const char*>(&tcpCheckExtraLen), 1);
 | 
				
			||||||
 | 
					      _conn->append(reinterpret_cast<const char*>(tcpCheckExtra), tcpCheckExtraLen);
 | 
				
			||||||
 | 
					      _conn->append(reinterpret_cast<const char*>(&sshUploadExtraLen), 1);
 | 
				
			||||||
 | 
					      _conn->append(reinterpret_cast<const char*>(sshUploadExtra), sshUploadExtraLen);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      //not arduino
 | 
				
			||||||
 | 
					      //we should figure out an API so TXT properties can be added for services
 | 
				
			||||||
 | 
					      uint8_t txt[2] = {0,0};
 | 
				
			||||||
 | 
					      _conn->append(reinterpret_cast<const char*>(txt), 2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // SRV Response
 | 
					  // SRV Response
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -78,11 +78,13 @@ public:
 | 
				
			|||||||
    addService(service.c_str(), proto.c_str(), port);
 | 
					    addService(service.c_str(), proto.c_str(), port);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 | 
					  void enableArduino(uint16_t port, bool auth=false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
  struct MDNSService * _services;
 | 
					  struct MDNSService * _services;
 | 
				
			||||||
  UdpContext* _conn;
 | 
					  UdpContext* _conn;
 | 
				
			||||||
  char _hostName[128];
 | 
					  char _hostName[128];
 | 
				
			||||||
  char _boardName[64];
 | 
					  bool _arduinoAuth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  uint32_t _getOurIp();
 | 
					  uint32_t _getOurIp();
 | 
				
			||||||
  uint16_t _getServicePort(char *service, char *proto);
 | 
					  uint16_t _getServicePort(char *service, char *proto);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,101 +0,0 @@
 | 
				
			|||||||
#include <ESP8266WiFi.h>
 | 
					 | 
				
			||||||
#include <ESP8266mDNS.h>
 | 
					 | 
				
			||||||
#include <WiFiUdp.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const char* host = "esp8266-ota";
 | 
					 | 
				
			||||||
const char* ssid = "**********";
 | 
					 | 
				
			||||||
const char* pass = "**********";
 | 
					 | 
				
			||||||
const uint16_t aport = 8266;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WiFiServer TelnetServer(aport);
 | 
					 | 
				
			||||||
WiFiClient Telnet;
 | 
					 | 
				
			||||||
WiFiUDP OTA;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void setup() {
 | 
					 | 
				
			||||||
  Serial.begin(115200);
 | 
					 | 
				
			||||||
  Serial.println("");
 | 
					 | 
				
			||||||
  Serial.println("Arduino OTA Test");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Serial.printf("Sketch size: %u\n", ESP.getSketchSize());
 | 
					 | 
				
			||||||
  Serial.printf("Free size: %u\n", ESP.getFreeSketchSpace());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  WiFi.begin(ssid, pass);
 | 
					 | 
				
			||||||
  if(WiFi.waitForConnectResult() == WL_CONNECTED){
 | 
					 | 
				
			||||||
    MDNS.begin(host);
 | 
					 | 
				
			||||||
    MDNS.addService("arduino", "tcp", aport);
 | 
					 | 
				
			||||||
    OTA.begin(aport);
 | 
					 | 
				
			||||||
    TelnetServer.begin();
 | 
					 | 
				
			||||||
    TelnetServer.setNoDelay(true);
 | 
					 | 
				
			||||||
    Serial.print("IP address: ");
 | 
					 | 
				
			||||||
    Serial.println(WiFi.localIP());
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void loop() {
 | 
					 | 
				
			||||||
  //OTA Sketch
 | 
					 | 
				
			||||||
  if (OTA.parsePacket()) {
 | 
					 | 
				
			||||||
    IPAddress remote = OTA.remoteIP();
 | 
					 | 
				
			||||||
    int cmd  = OTA.parseInt();
 | 
					 | 
				
			||||||
    int port = OTA.parseInt();
 | 
					 | 
				
			||||||
    int size   = OTA.parseInt();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Serial.print("Update Start: ip:");
 | 
					 | 
				
			||||||
    Serial.print(remote);
 | 
					 | 
				
			||||||
    Serial.printf(", port:%d, size:%d\n", port, size);
 | 
					 | 
				
			||||||
    uint32_t startTime = millis();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    WiFiUDP::stopAll();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(!Update.begin(size)){
 | 
					 | 
				
			||||||
      Serial.println("Update Begin Error");
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    WiFiClient client;
 | 
					 | 
				
			||||||
    if (client.connect(remote, port)) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      uint32_t written;
 | 
					 | 
				
			||||||
      while(!Update.isFinished()){
 | 
					 | 
				
			||||||
        written = Update.write(client);
 | 
					 | 
				
			||||||
        if(written > 0) client.print(written, DEC);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      Serial.setDebugOutput(false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(Update.end()){
 | 
					 | 
				
			||||||
        client.println("OK");
 | 
					 | 
				
			||||||
        Serial.printf("Update Success: %u\nRebooting...\n", millis() - startTime);
 | 
					 | 
				
			||||||
        ESP.restart();
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        Update.printError(client);
 | 
					 | 
				
			||||||
        Update.printError(Serial);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      Serial.printf("Connect Failed: %u\n", millis() - startTime);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  //IDE Monitor (connected to Serial)
 | 
					 | 
				
			||||||
  if (TelnetServer.hasClient()){
 | 
					 | 
				
			||||||
    if (!Telnet || !Telnet.connected()){
 | 
					 | 
				
			||||||
      if(Telnet) Telnet.stop();
 | 
					 | 
				
			||||||
      Telnet = TelnetServer.available();
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      WiFiClient toKill = TelnetServer.available();
 | 
					 | 
				
			||||||
      toKill.stop();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (Telnet && Telnet.connected() && Telnet.available()){
 | 
					 | 
				
			||||||
    while(Telnet.available())
 | 
					 | 
				
			||||||
      Serial.write(Telnet.read());
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if(Serial.available()){
 | 
					 | 
				
			||||||
    size_t len = Serial.available();
 | 
					 | 
				
			||||||
    uint8_t * sbuf = (uint8_t *)malloc(len);
 | 
					 | 
				
			||||||
    Serial.readBytes(sbuf, len);
 | 
					 | 
				
			||||||
    if (Telnet && Telnet.connected()){
 | 
					 | 
				
			||||||
      Telnet.write((uint8_t *)sbuf, len);
 | 
					 | 
				
			||||||
      yield();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    free(sbuf);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  delay(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -38,10 +38,6 @@ const char* ap_default_psk = "esp8266esp8266"; ///< Default PSK.
 | 
				
			|||||||
/// Uncomment the next line for verbose output over UART.
 | 
					/// Uncomment the next line for verbose output over UART.
 | 
				
			||||||
//#define SERIAL_VERBOSE
 | 
					//#define SERIAL_VERBOSE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// OTA server handle.
 | 
					 | 
				
			||||||
ArduinoOTA ota_server;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @brief Read WiFi connection information from file system.
 | 
					 * @brief Read WiFi connection information from file system.
 | 
				
			||||||
 * @param ssid String pointer for storing SSID.
 | 
					 * @param ssid String pointer for storing SSID.
 | 
				
			||||||
@@ -244,7 +240,8 @@ void setup()
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Start OTA server.
 | 
					  // Start OTA server.
 | 
				
			||||||
  ota_server.setup();
 | 
					  ArduinoOTA.setHostname((const char *)hostname.c_str());
 | 
				
			||||||
 | 
					  ArduinoOTA.begin();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -254,7 +251,7 @@ void setup()
 | 
				
			|||||||
void loop()
 | 
					void loop()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  // Handle OTA server.
 | 
					  // Handle OTA server.
 | 
				
			||||||
  ota_server.handle();
 | 
					  ArduinoOTA.handle();
 | 
				
			||||||
  yield();
 | 
					  yield();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@ MDNS	KEYWORD1
 | 
				
			|||||||
begin	KEYWORD2
 | 
					begin	KEYWORD2
 | 
				
			||||||
update	KEYWORD2
 | 
					update	KEYWORD2
 | 
				
			||||||
addService	KEYWORD2
 | 
					addService	KEYWORD2
 | 
				
			||||||
 | 
					enableArduino	KEYWORD2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#######################################
 | 
					#######################################
 | 
				
			||||||
# Constants (LITERAL1)
 | 
					# Constants (LITERAL1)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								platform.txt
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								platform.txt
									
									
									
									
									
								
							@@ -92,18 +92,18 @@ recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).*
 | 
				
			|||||||
tools.esptool.cmd=esptool
 | 
					tools.esptool.cmd=esptool
 | 
				
			||||||
tools.esptool.cmd.windows=esptool.exe
 | 
					tools.esptool.cmd.windows=esptool.exe
 | 
				
			||||||
tools.esptool.path={runtime.platform.path}/tools/esptool
 | 
					tools.esptool.path={runtime.platform.path}/tools/esptool
 | 
				
			||||||
#runtime.tools.esptool.path
 | 
					tools.esptool.network_cmd=python
 | 
				
			||||||
 | 
					tools.esptool.network_cmd.windows=python.exe
 | 
				
			||||||
tools.mkspiffs.cmd=mkspiffs
 | 
					 | 
				
			||||||
tools.mkspiffs.cmd.windows=mkspiffs.exe
 | 
					 | 
				
			||||||
tools.mkspiffs.path={runtime.platform.path}/tools/mkspiffs
 | 
					 | 
				
			||||||
#runtime.tools.mkspiffs.path
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
tools.esptool.upload.protocol=esp
 | 
					tools.esptool.upload.protocol=esp
 | 
				
			||||||
tools.esptool.upload.params.verbose=-vv
 | 
					tools.esptool.upload.params.verbose=-vv
 | 
				
			||||||
tools.esptool.upload.params.quiet=
 | 
					tools.esptool.upload.params.quiet=
 | 
				
			||||||
tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" -ca 0x00000 -cf "{build.path}/{build.project_name}.bin"
 | 
					tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" -ca 0x00000 -cf "{build.path}/{build.project_name}.bin"
 | 
				
			||||||
tools.esptool.network.pattern=python "{path}/espota.py" -i "{serial.port}" -p "{network.port}" -f "{build.path}/{build.project_name}.bin"
 | 
					tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tools.mkspiffs.cmd=mkspiffs
 | 
				
			||||||
 | 
					tools.mkspiffs.cmd.windows=mkspiffs.exe
 | 
				
			||||||
 | 
					tools.mkspiffs.path={runtime.platform.path}/tools/mkspiffs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tools.espota.cmd=python
 | 
					tools.espota.cmd=python
 | 
				
			||||||
tools.espota.cmd.windows=python.exe
 | 
					tools.espota.cmd.windows=python.exe
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,11 +4,12 @@
 | 
				
			|||||||
# https://gist.github.com/igrr/d35ab8446922179dc58c
 | 
					# https://gist.github.com/igrr/d35ab8446922179dc58c
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Modified since 2015-09-18 from Pascal Gollor (https://github.com/pgollor)
 | 
					# Modified since 2015-09-18 from Pascal Gollor (https://github.com/pgollor)
 | 
				
			||||||
 | 
					# Modified since 2015-11-09 from Hristo Gochkov (https://github.com/me-no-dev)
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# This script will push an OTA update to the ESP
 | 
					# This script will push an OTA update to the ESP
 | 
				
			||||||
# use it like: python espota.py -i <ESP_IP_address> -p <ESP_port> -f <sketch.bin>
 | 
					# use it like: python espota.py -i <ESP_IP_address> -p <ESP_port> [-a password] -f <sketch.bin>
 | 
				
			||||||
# Or to upload SPIFFS image:
 | 
					# Or to upload SPIFFS image:
 | 
				
			||||||
# python espota.py -i <ESP_IP_address> -p <ESP_port> -s -f <spiffs.bin>
 | 
					# python espota.py -i <ESP_IP_address> -p <ESP_port> [-a password] -s -f <spiffs.bin>
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Changes
 | 
					# Changes
 | 
				
			||||||
# 2015-09-18:
 | 
					# 2015-09-18:
 | 
				
			||||||
@@ -16,6 +17,11 @@
 | 
				
			|||||||
# - Add logging.
 | 
					# - Add logging.
 | 
				
			||||||
# - Send command to controller to differ between flashing and transmitting SPIFFS image.
 | 
					# - Send command to controller to differ between flashing and transmitting SPIFFS image.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					# Changes
 | 
				
			||||||
 | 
					# 2015-11-09:
 | 
				
			||||||
 | 
					# - Added digest authentication
 | 
				
			||||||
 | 
					# - Enchanced error tracking and reporting
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from __future__ import print_function
 | 
					from __future__ import print_function
 | 
				
			||||||
import socket
 | 
					import socket
 | 
				
			||||||
@@ -23,13 +29,15 @@ import sys
 | 
				
			|||||||
import os
 | 
					import os
 | 
				
			||||||
import optparse
 | 
					import optparse
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
 | 
					import hashlib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Commands
 | 
					# Commands
 | 
				
			||||||
FLASH = 0
 | 
					FLASH = 0
 | 
				
			||||||
SPIFFS = 100
 | 
					SPIFFS = 100
 | 
				
			||||||
 | 
					AUTH = 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def serve(remoteAddr, remotePort, filename, command = FLASH):
 | 
					def serve(remoteAddr, remotePort, password, filename, command = FLASH):
 | 
				
			||||||
  # Create a TCP/IP socket
 | 
					  # Create a TCP/IP socket
 | 
				
			||||||
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 | 
					  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 | 
				
			||||||
  serverPort = 48266
 | 
					  serverPort = 48266
 | 
				
			||||||
@@ -43,17 +51,58 @@ def serve(remoteAddr, remotePort, filename, command = FLASH):
 | 
				
			|||||||
    return 1
 | 
					    return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  content_size = os.path.getsize(filename)
 | 
					  content_size = os.path.getsize(filename)
 | 
				
			||||||
 | 
					  f = open(filename,'rb')
 | 
				
			||||||
 | 
					  file_md5 = hashlib.md5(f.read()).hexdigest()
 | 
				
			||||||
 | 
					  f.close()
 | 
				
			||||||
  logging.info('Upload size: %d', content_size)
 | 
					  logging.info('Upload size: %d', content_size)
 | 
				
			||||||
  message = '%d %d %d\n' % (command, serverPort, content_size)
 | 
					  message = '%d %d %d %s\n' % (command, serverPort, content_size, file_md5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Wait for a connection
 | 
					  # Wait for a connection
 | 
				
			||||||
  logging.info('Sending invitation to: %s', remoteAddr)
 | 
					  logging.info('Sending invitation to: %s', remoteAddr)
 | 
				
			||||||
  sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 | 
					  sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 | 
				
			||||||
  remote_address = (remoteAddr, int(remotePort))
 | 
					  remote_address = (remoteAddr, int(remotePort))
 | 
				
			||||||
  sent = sock2.sendto(message, remote_address)
 | 
					  sent = sock2.sendto(message, remote_address)
 | 
				
			||||||
 | 
					  sock2.settimeout(10)
 | 
				
			||||||
 | 
					  try:
 | 
				
			||||||
 | 
					    data = sock2.recv(37)
 | 
				
			||||||
 | 
					  except:
 | 
				
			||||||
 | 
					    logging.error('No Answer')
 | 
				
			||||||
 | 
					    sock2.close()
 | 
				
			||||||
 | 
					    return 1
 | 
				
			||||||
 | 
					  if (data != "OK"):
 | 
				
			||||||
 | 
					    if(data.startswith('AUTH')):
 | 
				
			||||||
 | 
					      nonce = data.split()[1]
 | 
				
			||||||
 | 
					      cnonce_text = '%s%u%s%s' % (filename, content_size, file_md5, remoteAddr)
 | 
				
			||||||
 | 
					      cnonce = hashlib.md5(cnonce_text).hexdigest()
 | 
				
			||||||
 | 
					      passmd5 = hashlib.md5(password).hexdigest()
 | 
				
			||||||
 | 
					      result_text = '%s:%s:%s' % (passmd5 ,nonce, cnonce)
 | 
				
			||||||
 | 
					      result = hashlib.md5(result_text).hexdigest()
 | 
				
			||||||
 | 
					      sys.stderr.write('Authenticating...')
 | 
				
			||||||
 | 
					      sys.stderr.flush()
 | 
				
			||||||
 | 
					      message = '%d %s %s\n' % (AUTH, cnonce, result)
 | 
				
			||||||
 | 
					      sock2.sendto(message, remote_address)
 | 
				
			||||||
 | 
					      sock2.settimeout(10)
 | 
				
			||||||
 | 
					      try:
 | 
				
			||||||
 | 
					        data = sock2.recv(32)
 | 
				
			||||||
 | 
					      except:
 | 
				
			||||||
 | 
					        sys.stderr.write('FAIL\n')
 | 
				
			||||||
 | 
					        logging.error('No Answer to our Authentication')
 | 
				
			||||||
 | 
					        sock2.close()
 | 
				
			||||||
 | 
					        return 1
 | 
				
			||||||
 | 
					      if (data != "OK"):
 | 
				
			||||||
 | 
					        sys.stderr.write('FAIL\n')
 | 
				
			||||||
 | 
					        logging.error('%s', data)
 | 
				
			||||||
 | 
					        sock2.close()
 | 
				
			||||||
 | 
					        sys.exit(1);
 | 
				
			||||||
 | 
					        return 1
 | 
				
			||||||
 | 
					      sys.stderr.write('OK\n')
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					      logging.error('Bad Answer: %s', data)
 | 
				
			||||||
 | 
					      sock2.close()
 | 
				
			||||||
 | 
					      return 1
 | 
				
			||||||
  sock2.close()
 | 
					  sock2.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  logging.info('Waiting for device...\n')
 | 
					  logging.info('Waiting for device...')
 | 
				
			||||||
  try:
 | 
					  try:
 | 
				
			||||||
    sock.settimeout(10)
 | 
					    sock.settimeout(10)
 | 
				
			||||||
    connection, client_address = sock.accept()
 | 
					    connection, client_address = sock.accept()
 | 
				
			||||||
@@ -78,13 +127,15 @@ def serve(remoteAddr, remotePort, filename, command = FLASH):
 | 
				
			|||||||
        connection.sendall(chunk)
 | 
					        connection.sendall(chunk)
 | 
				
			||||||
        res = connection.recv(4)
 | 
					        res = connection.recv(4)
 | 
				
			||||||
      except:
 | 
					      except:
 | 
				
			||||||
        logging.error('\nError Uploading')
 | 
					        sys.stderr.write('\n')
 | 
				
			||||||
 | 
					        logging.error('Error Uploading')
 | 
				
			||||||
        connection.close()
 | 
					        connection.close()
 | 
				
			||||||
        f.close()
 | 
					        f.close()
 | 
				
			||||||
        sock.close()
 | 
					        sock.close()
 | 
				
			||||||
        return 1
 | 
					        return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    logging.info('\nWaiting for result...\n')
 | 
					    sys.stderr.write('\n')
 | 
				
			||||||
 | 
					    logging.info('Waiting for result...')
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
      connection.settimeout(60)
 | 
					      connection.settimeout(60)
 | 
				
			||||||
      data = connection.recv(32)
 | 
					      data = connection.recv(32)
 | 
				
			||||||
@@ -92,9 +143,13 @@ def serve(remoteAddr, remotePort, filename, command = FLASH):
 | 
				
			|||||||
      connection.close()
 | 
					      connection.close()
 | 
				
			||||||
      f.close()
 | 
					      f.close()
 | 
				
			||||||
      sock.close()
 | 
					      sock.close()
 | 
				
			||||||
 | 
					      if (data != "OK"):
 | 
				
			||||||
 | 
					        sys.stderr.write('\n')
 | 
				
			||||||
 | 
					        logging.error('%s', data)
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
      return 0
 | 
					      return 0
 | 
				
			||||||
    except:
 | 
					    except:
 | 
				
			||||||
      logging.error('Result: No Answer!')
 | 
					      logging.error('No Result!')
 | 
				
			||||||
      connection.close()
 | 
					      connection.close()
 | 
				
			||||||
      f.close()
 | 
					      f.close()
 | 
				
			||||||
      sock.close()
 | 
					      sock.close()
 | 
				
			||||||
@@ -131,6 +186,16 @@ def parser():
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
	parser.add_option_group(group)
 | 
						parser.add_option_group(group)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# auth
 | 
				
			||||||
 | 
						group = optparse.OptionGroup(parser, "Authentication")
 | 
				
			||||||
 | 
						group.add_option("-a", "--auth",
 | 
				
			||||||
 | 
							dest = "auth",
 | 
				
			||||||
 | 
							help = "Set authentication password.",
 | 
				
			||||||
 | 
							action = "store",
 | 
				
			||||||
 | 
							default = ""
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						parser.add_option_group(group)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# image
 | 
						# image
 | 
				
			||||||
	group = optparse.OptionGroup(parser, "Image")
 | 
						group = optparse.OptionGroup(parser, "Image")
 | 
				
			||||||
	group.add_option("-f", "--file",
 | 
						group.add_option("-f", "--file",
 | 
				
			||||||
@@ -190,7 +255,7 @@ def main(args):
 | 
				
			|||||||
		command = SPIFFS
 | 
							command = SPIFFS
 | 
				
			||||||
	# end if
 | 
						# end if
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return serve(options.esp_ip, options.esp_port, options.image, command)
 | 
						return serve(options.esp_ip, options.esp_port, options.auth, options.image, command)
 | 
				
			||||||
# end main
 | 
					# end main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user