created: usersensor, bme680 bsec, update arduino-esp32 core
This commit is contained in:
1 parent
4e6c2b8b38
commit
467f6d70f8
80 files changed
+23464
-626
No files matched your search
@@ -16,6 +16,9 @@ void gps_read() {
|
||||
gps_status.satellites = (uint8_t)gps.satellites.value();
|
||||
gps_status.hdop = (uint16_t)gps.hdop.value();
|
||||
gps_status.altitude = (int16_t)gps.altitude.meters();
|
||||
// show NMEA data in debug mode, useful for debugging GPS
|
||||
ESP_LOGD(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d",
|
||||
gps.passedChecksum(), gps.failedChecksum(), gps.sentencesWithFix());
|
||||
}
|
||||
|
||||
// GPS serial feed FreeRTos Task
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (27)
|
||||
#define LORA_RST (14)
|
||||
#define LORA_IO0 (26)
|
||||
#define LORA_IRQ (26)
|
||||
#define LORA_IO1 (33)
|
||||
#define LORA_IO2 LMIC_UNUSED_PIN
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (27)
|
||||
#define LORA_RST (14)
|
||||
#define LORA_IO0 (26)
|
||||
#define LORA_IRQ (26)
|
||||
#define LORA_IO1 (33)
|
||||
#define LORA_IO2 (32)
|
||||
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (27)
|
||||
#define LORA_RST LMIC_UNUSED_PIN
|
||||
#define LORA_IO0 (23) // LoRa IRQ
|
||||
#define LORA_IRQ (23) // LoRa IRQ
|
||||
#define LORA_IO1 (23) // Pin tied via diode to DIO0
|
||||
#define LORA_IO2 LMIC_UNUSED_PIN
|
||||
|
||||
|
||||
+3
-1
@@ -15,6 +15,8 @@
|
||||
|
||||
#define HAS_BME 0x77 // BME680 sensor on I2C bus (SDA=4/SCL=15); comment out if not present
|
||||
|
||||
#define HAS_SENSORS 1 // comment out if device has user defined sensors
|
||||
|
||||
#define CFG_sx1276_radio 1 // select LoRa chip
|
||||
//#define CFG_sx1272_radio 1 // select LoRa chip
|
||||
#define BOARD_HAS_PSRAM // use if board has external PSRAM
|
||||
@@ -45,7 +47,7 @@
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (27)
|
||||
#define LORA_RST (14)
|
||||
#define LORA_IO0 (26)
|
||||
#define LORA_IRQ (26)
|
||||
#define LORA_IO1 (33)
|
||||
#define LORA_IO2 LMIC_UNUSED_PIN
|
||||
|
||||
|
||||
+9
-13
@@ -3,28 +3,24 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//#define HAS_BME 0x77 // BME680 sensor on I2C bus (SDI=21/SCL=22); comment out if not present
|
||||
//#define HAS_BME 0x77 // BME680 sensor on I2C bus (SDI=21/SCL=22); comment out
|
||||
//if not present
|
||||
|
||||
// Hardware related definitions for Heltec LoRa-32 Board
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
#define CFG_sx1276_radio 1
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board
|
||||
#define HAS_LED (25) // white LED on board
|
||||
#define HAS_BUTTON (0) // button "PROG" on board
|
||||
#define HAS_LED (25) // white LED on board
|
||||
#define HAS_BUTTON (0) // button "PROG" on board
|
||||
|
||||
// Pins for I2C interface of OLED Display
|
||||
#define MY_OLED_SDA (4)
|
||||
#define MY_OLED_SCL (15)
|
||||
#define MY_OLED_RST (16)
|
||||
|
||||
// Pins for LORA chip SPI interface, reset line and interrupt lines
|
||||
#define LORA_SCK (5)
|
||||
#define LORA_CS (18)
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (27)
|
||||
#define LORA_RST (14)
|
||||
#define LORA_IO0 (26)
|
||||
#define LORA_IO1 (33)
|
||||
#define LORA_IO2 LMIC_UNUSED_PIN
|
||||
// Pins for LORA chip SPI interface come from board file, we need some
|
||||
// additional definitions for LMIC
|
||||
#define LORA_IO1 (33)
|
||||
#define LORA_IO2 LMIC_UNUSED_PIN
|
||||
|
||||
#endif
|
||||
+2
-7
@@ -17,13 +17,8 @@
|
||||
#define OLED_SCL (15)
|
||||
#define OLED_RST (16)
|
||||
|
||||
// Pins for LORA chip SPI interface, reset line and interrupt lines
|
||||
#define LORA_SCK (5)
|
||||
#define LORA_CS (18)
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (27)
|
||||
#define LORA_RST (14)
|
||||
#define LORA_IO0 (26)
|
||||
// Pins for LORA chip SPI interface come from board file, we need some
|
||||
// additional definitions for LMIC
|
||||
#define LORA_IO1 (35)
|
||||
#define LORA_IO2 (34)
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (27)
|
||||
#define LORA_RST (25)
|
||||
#define LORA_IO0 (27)
|
||||
#define LORA_IRQ (27)
|
||||
#define LORA_IO1 (26)
|
||||
#define LORA_IO2 LMIC_UNUSED_PIN
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (27)
|
||||
#define LORA_RST (25)
|
||||
#define LORA_IO0 (27)
|
||||
#define LORA_IRQ (27)
|
||||
#define LORA_IO1 (26)
|
||||
#define LORA_IO2 LMIC_UNUSED_PIN
|
||||
#define LORA_IO5 LMIC_UNUSED_PIN
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
#define LORA_MISO (19) // GPIO19 - SX1276 MISO
|
||||
#define LORA_MOSI (27) // GPIO27 - SX1276 MOSI
|
||||
#define LORA_RST (18) // GPIO18 - SX1276 RESET
|
||||
#define LORA_IO0 (23) // LoRa IRQ
|
||||
#define LORA_IRQ (23) // LoRa IRQ
|
||||
#define LORA_IO1 (23) // Pin tied via diode to DIO0
|
||||
#define LORA_IO2 (23) // Pin tied via diode to DIO0
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (27)
|
||||
#define LORA_RST LMIC_UNUSED_PIN
|
||||
#define LORA_IO0 (23) // LoRa IRQ
|
||||
#define LORA_IRQ (23) // LoRa IRQ
|
||||
#define LORA_IO1 (23) // Pin tied via diode to DIO0
|
||||
#define LORA_IO2 (23) // Pin tied via diode to DIO0
|
||||
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (18)
|
||||
#define LORA_RST LMIC_UNUSED_PIN
|
||||
#define LORA_IO0 (33)
|
||||
#define LORA_IRQ (33)
|
||||
#define LORA_IO1 (33)
|
||||
#define LORA_IO2 LMIC_UNUSED_PIN
|
||||
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (27)
|
||||
#define LORA_RST LMIC_UNUSED_PIN
|
||||
#define LORA_IO0 (26)
|
||||
#define LORA_IRQ (26)
|
||||
#define LORA_IO1 (32) // !! NEEDS EXTERNAL WIRING !!
|
||||
//#define LORA_IO1 (33) // for T-Beam T22_V05 and T22_V07, other versions may need external wiring
|
||||
#define LORA_IO2 LMIC_UNUSED_PIN
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (27)
|
||||
#define LORA_RST (14)
|
||||
#define LORA_IO0 (26)
|
||||
#define LORA_IRQ (26)
|
||||
#define LORA_IO1 (33)
|
||||
#define LORA_IO2 LMIC_UNUSED_PIN
|
||||
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (27)
|
||||
#define LORA_RST LMIC_UNUSED_PIN
|
||||
#define LORA_IO0 (26)
|
||||
#define LORA_IRQ (26)
|
||||
#define LORA_IO1 (33)
|
||||
#define LORA_IO2 LMIC_UNUSED_PIN
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (27)
|
||||
#define LORA_RST (23)
|
||||
#define LORA_IO0 (26)
|
||||
#define LORA_IRQ (26)
|
||||
#define LORA_IO1 (33)
|
||||
#define LORA_IO2 (32)
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#define LORA_MISO (19)
|
||||
#define LORA_MOSI (27)
|
||||
#define LORA_RST LMIC_UNUSED_PIN
|
||||
#define LORA_IO0 (26)
|
||||
#define LORA_IRQ (26)
|
||||
#define LORA_IO1 (33)
|
||||
#define LORA_IO2 (32)
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ const lmic_pinmap lmic_pins = {
|
||||
.nss = LORA_CS,
|
||||
.rxtx = LMIC_UNUSED_PIN,
|
||||
.rst = LORA_RST,
|
||||
.dio = {LORA_IO0, LORA_IO1, LORA_IO2},
|
||||
.dio = {LORA_IRQ, LORA_IO1, LORA_IO2},
|
||||
.mosi = LORA_MOSI,
|
||||
.miso = LORA_MISO,
|
||||
.sck = LORA_SCK
|
||||
|
||||
+1
-3
@@ -146,9 +146,7 @@ int do_ota_update() {
|
||||
WiFiClientSecure client;
|
||||
|
||||
client.setCACert(bintray.getCertificate(currentHost));
|
||||
// client.setTimeout(RESPONSE_TIMEOUT_MS);
|
||||
// --> causing error [E][WiFiClient.cpp:236] setSocketOption(): 1006 : 9
|
||||
// so we unfortunately need patched update.cpp which sets the stream timeout
|
||||
client.setTimeout(RESPONSE_TIMEOUT_MS);
|
||||
|
||||
if (!client.connect(currentHost.c_str(), port)) {
|
||||
ESP_LOGI(TAG, "Cannot connect to %s", currentHost.c_str());
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// Payload send cycle and encoding
|
||||
#define SEND_SECS 30 // payload send cycle [seconds/2] -> 60 sec.
|
||||
#define PAYLOAD_ENCODER 2 // payload encoder: 1=Plain, 2=Packed, 3=CayenneLPP dynamic, 4=CayenneLPP packed
|
||||
#define SENSORBUFFER 20 // size of user sensor data buffer in bytes [default=20]
|
||||
|
||||
// Set this to include BLE counting and vendor filter functions
|
||||
#define VENDORFILTER 1 // comment out if you want to count things, not people
|
||||
@@ -60,6 +61,10 @@
|
||||
#define LPP2PORT 2 // Port for Cayenne LPP 2.0 packed sensor encoding
|
||||
#define BEACONPORT 6 // Port on which device sends beacon alarms
|
||||
#define BMEPORT 7 // Port on which device sends BME680 sensor data
|
||||
#define SENSOR1PORT 10 // Port on which device sends User sensor #1 data
|
||||
#define SENSOR2PORT 11 // Port on which device sends User sensor #2 data
|
||||
#define SENSOR3PORT 12 // Port on which device sends User sensor #3 data
|
||||
#define SENSOR4PORT 13 // Port on which device sends User sensor #4 data
|
||||
|
||||
// Some hardware settings
|
||||
#define RGBLUMINOSITY 30 // RGB LED luminosity [default = 30%]
|
||||
|
||||
+27
-1
@@ -1,4 +1,3 @@
|
||||
|
||||
#include "globals.h"
|
||||
#include "payload.h"
|
||||
|
||||
@@ -93,6 +92,14 @@ void PayloadConvert::addGPS(gpsStatus_t value) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void PayloadConvert::addSensor(uint8_t buf[]) {
|
||||
#ifdef HAS_SENSORS
|
||||
uint8_t length = buf[0];
|
||||
memcpy(buffer, buf + 1, length);
|
||||
cursor += length; // length of buffer
|
||||
#endif
|
||||
}
|
||||
|
||||
void PayloadConvert::addBME(bmeStatus_t value) {
|
||||
#ifdef HAS_BME
|
||||
int16_t temperature = (int16_t)(value.temperature); // float -> int
|
||||
@@ -174,6 +181,14 @@ void PayloadConvert::addGPS(gpsStatus_t value) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void PayloadConvert::addSensor(uint8_t buf[]) {
|
||||
#ifdef HAS_SENSORS
|
||||
uint8_t length = buf[0];
|
||||
memcpy(buffer, buf + 1, length);
|
||||
cursor += length; // length of buffer
|
||||
#endif
|
||||
}
|
||||
|
||||
void PayloadConvert::addBME(bmeStatus_t value) {
|
||||
#ifdef HAS_BME
|
||||
writeTemperature(value.temperature);
|
||||
@@ -337,6 +352,17 @@ void PayloadConvert::addGPS(gpsStatus_t value) {
|
||||
#endif // HAS_GPS
|
||||
}
|
||||
|
||||
void PayloadConvert::addSensor(uint8_t buf[]) {
|
||||
#ifdef HAS_SENSORS
|
||||
// to come
|
||||
/*
|
||||
uint8_t length = buf[0];
|
||||
memcpy(buffer, buf+1, length);
|
||||
cursor += length; // length of buffer
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
void PayloadConvert::addBME(bmeStatus_t value) {
|
||||
#ifdef HAS_BME
|
||||
|
||||
|
||||
+35
-15
@@ -25,11 +25,10 @@ void sendCounter() {
|
||||
uint8_t mask = 1;
|
||||
|
||||
while (bitmask) {
|
||||
|
||||
payload.reset();
|
||||
switch (bitmask & mask) {
|
||||
|
||||
case COUNT_DATA:
|
||||
payload.reset();
|
||||
payload.addCount(macs_wifi, cfg.blescan ? macs_ble : 0);
|
||||
SendPayload(COUNTERPORT);
|
||||
// clear counter if not in cumulative counter mode
|
||||
@@ -40,33 +39,54 @@ void sendCounter() {
|
||||
}
|
||||
break;
|
||||
|
||||
case MEMS_DATA:
|
||||
#ifdef HAS_BME
|
||||
case MEMS_DATA:
|
||||
payload.reset();
|
||||
payload.addBME(bme_status);
|
||||
SendPayload(BMEPORT);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
|
||||
case GPS_DATA:
|
||||
#ifdef HAS_GPS
|
||||
// show NMEA data in debug mode, useful for debugging GPS
|
||||
ESP_LOGD(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d",
|
||||
gps.passedChecksum(), gps.failedChecksum(),
|
||||
gps.sentencesWithFix());
|
||||
case GPS_DATA:
|
||||
// send GPS position only if we have a fix
|
||||
if (gps.location.isValid()) {
|
||||
ESP_LOGD(TAG,
|
||||
"lat=%.6f | lon=%.6f | %u Sats | HDOP=%.1f | Altitude=%um",
|
||||
gps_status.latitude / (float)1e6,
|
||||
gps_status.longitude / (float)1e6, gps_status.satellites,
|
||||
gps_status.hdop / (float)100, gps_status.altitude);
|
||||
gps_read();
|
||||
payload.reset();
|
||||
payload.addGPS(gps_status);
|
||||
SendPayload(GPSPORT);
|
||||
} else
|
||||
ESP_LOGD(TAG, "No valid GPS position");
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SENSORS
|
||||
|
||||
case SENSOR1_DATA:
|
||||
payload.reset();
|
||||
payload.addSensor(sensor_read(1));
|
||||
SendPayload(SENSOR1PORT);
|
||||
break;
|
||||
|
||||
case SENSOR2_DATA:
|
||||
payload.reset();
|
||||
payload.addSensor(sensor_read(2));
|
||||
SendPayload(SENSOR2PORT);
|
||||
break;
|
||||
|
||||
case SENSOR3_DATA:
|
||||
payload.reset();
|
||||
payload.addSensor(sensor_read(3));
|
||||
SendPayload(SENSOR3PORT);
|
||||
break;
|
||||
|
||||
case SENSOR4_DATA:
|
||||
payload.reset();
|
||||
payload.addSensor(sensor_read(4));
|
||||
SendPayload(SENSOR4PORT);
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
} // switch
|
||||
bitmask &= ~mask;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// Basic Config
|
||||
#include "globals.h"
|
||||
|
||||
// Local logging tag
|
||||
static const char TAG[] = "main";
|
||||
|
||||
uint8_t * sensor_read(uint8_t sensor) {
|
||||
|
||||
static uint8_t buf[SENSORBUFFER] = {0};
|
||||
uint8_t length = 3;
|
||||
|
||||
switch (sensor) {
|
||||
|
||||
case 1:
|
||||
|
||||
buf[0] = length;
|
||||
buf[1] = 0xff;
|
||||
buf[2] = 0xa0;
|
||||
buf[3] = 0x01;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
buf[0] = length;
|
||||
buf[1] = 0xff;
|
||||
buf[2] = 0xa0;
|
||||
buf[3] = 0x02;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
||||
buf[0] = length;
|
||||
buf[1] = 0xff;
|
||||
buf[2] = 0xa0;
|
||||
buf[3] = 0x03;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
|
||||
buf[0] = length;
|
||||
buf[1] = 0xff;
|
||||
buf[2] = 0xa0;
|
||||
buf[3] = 0x04;
|
||||
break;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
-375
@@ -1,375 +0,0 @@
|
||||
/*
|
||||
this file copied from esp32-arduino library and patched, see PR
|
||||
https://github.com/espressif/arduino-esp32/pull/1979
|
||||
*/
|
||||
|
||||
#include "Update.h"
|
||||
#include "Arduino.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_image_format.h"
|
||||
|
||||
static const char * _err2str(uint8_t _error){
|
||||
if(_error == UPDATE_ERROR_OK){
|
||||
return ("No Error");
|
||||
} else if(_error == UPDATE_ERROR_WRITE){
|
||||
return ("Flash Write Failed");
|
||||
} else if(_error == UPDATE_ERROR_ERASE){
|
||||
return ("Flash Erase Failed");
|
||||
} else if(_error == UPDATE_ERROR_READ){
|
||||
return ("Flash Read Failed");
|
||||
} else if(_error == UPDATE_ERROR_SPACE){
|
||||
return ("Not Enough Space");
|
||||
} else if(_error == UPDATE_ERROR_SIZE){
|
||||
return ("Bad Size Given");
|
||||
} else if(_error == UPDATE_ERROR_STREAM){
|
||||
return ("Stream Read Timeout");
|
||||
} else if(_error == UPDATE_ERROR_MD5){
|
||||
return ("MD5 Check Failed");
|
||||
} else if(_error == UPDATE_ERROR_MAGIC_BYTE){
|
||||
return ("Wrong Magic Byte");
|
||||
} else if(_error == UPDATE_ERROR_ACTIVATE){
|
||||
return ("Could Not Activate The Firmware");
|
||||
} else if(_error == UPDATE_ERROR_NO_PARTITION){
|
||||
return ("Partition Could Not be Found");
|
||||
} else if(_error == UPDATE_ERROR_BAD_ARGUMENT){
|
||||
return ("Bad Argument");
|
||||
} else if(_error == UPDATE_ERROR_ABORT){
|
||||
return ("Aborted");
|
||||
}
|
||||
return ("UNKNOWN");
|
||||
}
|
||||
|
||||
static bool _partitionIsBootable(const esp_partition_t* partition){
|
||||
uint8_t buf[4];
|
||||
if(!partition){
|
||||
return false;
|
||||
}
|
||||
if(!ESP.flashRead(partition->address, (uint32_t*)buf, 4)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(buf[0] != ESP_IMAGE_HEADER_MAGIC) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _enablePartition(const esp_partition_t* partition){
|
||||
uint8_t buf[4];
|
||||
if(!partition){
|
||||
return false;
|
||||
}
|
||||
if(!ESP.flashRead(partition->address, (uint32_t*)buf, 4)) {
|
||||
return false;
|
||||
}
|
||||
buf[0] = ESP_IMAGE_HEADER_MAGIC;
|
||||
|
||||
return ESP.flashWrite(partition->address, (uint32_t*)buf, 4);
|
||||
}
|
||||
|
||||
UpdateClass::UpdateClass()
|
||||
: _error(0)
|
||||
, _buffer(0)
|
||||
, _bufferLen(0)
|
||||
, _size(0)
|
||||
, _progress_callback(NULL)
|
||||
, _progress(0)
|
||||
, _command(U_FLASH)
|
||||
, _partition(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
UpdateClass& UpdateClass::onProgress(THandlerFunction_Progress fn) {
|
||||
_progress_callback = fn;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void UpdateClass::_reset() {
|
||||
if (_buffer)
|
||||
delete[] _buffer;
|
||||
_buffer = 0;
|
||||
_bufferLen = 0;
|
||||
_progress = 0;
|
||||
_size = 0;
|
||||
_command = U_FLASH;
|
||||
|
||||
if(_ledPin != -1) {
|
||||
digitalWrite(_ledPin, !_ledOn); // off
|
||||
}
|
||||
}
|
||||
|
||||
bool UpdateClass::canRollBack(){
|
||||
if(_buffer){ //Update is running
|
||||
return false;
|
||||
}
|
||||
const esp_partition_t* partition = esp_ota_get_next_update_partition(NULL);
|
||||
return _partitionIsBootable(partition);
|
||||
}
|
||||
|
||||
bool UpdateClass::rollBack(){
|
||||
if(_buffer){ //Update is running
|
||||
return false;
|
||||
}
|
||||
const esp_partition_t* partition = esp_ota_get_next_update_partition(NULL);
|
||||
return _partitionIsBootable(partition) && !esp_ota_set_boot_partition(partition);
|
||||
}
|
||||
|
||||
bool UpdateClass::begin(size_t size, int command, int ledPin, uint8_t ledOn) {
|
||||
if(_size > 0){
|
||||
log_w("already running");
|
||||
return false;
|
||||
}
|
||||
|
||||
_ledPin = ledPin;
|
||||
_ledOn = !!ledOn; // 0(LOW) or 1(HIGH)
|
||||
|
||||
_reset();
|
||||
_error = 0;
|
||||
|
||||
if(size == 0) {
|
||||
_error = UPDATE_ERROR_SIZE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (command == U_FLASH) {
|
||||
_partition = esp_ota_get_next_update_partition(NULL);
|
||||
if(!_partition){
|
||||
_error = UPDATE_ERROR_NO_PARTITION;
|
||||
return false;
|
||||
}
|
||||
log_d("OTA Partition: %s", _partition->label);
|
||||
}
|
||||
else if (command == U_SPIFFS) {
|
||||
_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL);
|
||||
if(!_partition){
|
||||
_error = UPDATE_ERROR_NO_PARTITION;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_error = UPDATE_ERROR_BAD_ARGUMENT;
|
||||
log_e("bad command %u", command);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(size == UPDATE_SIZE_UNKNOWN){
|
||||
size = _partition->size;
|
||||
} else if(size > _partition->size){
|
||||
_error = UPDATE_ERROR_SIZE;
|
||||
log_e("too large %u > %u", size, _partition->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
//initialize
|
||||
_buffer = (uint8_t*)malloc(SPI_FLASH_SEC_SIZE);
|
||||
if(!_buffer){
|
||||
log_e("malloc failed");
|
||||
return false;
|
||||
}
|
||||
_size = size;
|
||||
_command = command;
|
||||
_md5.begin();
|
||||
return true;
|
||||
}
|
||||
|
||||
void UpdateClass::_abort(uint8_t err){
|
||||
_reset();
|
||||
_error = err;
|
||||
}
|
||||
|
||||
void UpdateClass::abort(){
|
||||
_abort(UPDATE_ERROR_ABORT);
|
||||
}
|
||||
|
||||
bool UpdateClass::_writeBuffer(){
|
||||
//first bytes of new firmware
|
||||
if(!_progress && _command == U_FLASH){
|
||||
//check magic
|
||||
if(_buffer[0] != ESP_IMAGE_HEADER_MAGIC){
|
||||
_abort(UPDATE_ERROR_MAGIC_BYTE);
|
||||
return false;
|
||||
}
|
||||
//remove magic byte from the firmware now and write it upon success
|
||||
//this ensures that partially written firmware will not be bootable
|
||||
_buffer[0] = 0xFF;
|
||||
}
|
||||
if(!ESP.flashEraseSector((_partition->address + _progress)/SPI_FLASH_SEC_SIZE)){
|
||||
_abort(UPDATE_ERROR_ERASE);
|
||||
return false;
|
||||
}
|
||||
if (!ESP.flashWrite(_partition->address + _progress, (uint32_t*)_buffer, _bufferLen)) {
|
||||
_abort(UPDATE_ERROR_WRITE);
|
||||
return false;
|
||||
}
|
||||
//restore magic or md5 will fail
|
||||
if(!_progress && _command == U_FLASH){
|
||||
_buffer[0] = ESP_IMAGE_HEADER_MAGIC;
|
||||
}
|
||||
_md5.add(_buffer, _bufferLen);
|
||||
_progress += _bufferLen;
|
||||
_bufferLen = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UpdateClass::_verifyHeader(uint8_t data) {
|
||||
if(_command == U_FLASH) {
|
||||
if(data != ESP_IMAGE_HEADER_MAGIC) {
|
||||
_abort(UPDATE_ERROR_MAGIC_BYTE);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else if(_command == U_SPIFFS) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateClass::_verifyEnd() {
|
||||
if(_command == U_FLASH) {
|
||||
if(!_enablePartition(_partition) || !_partitionIsBootable(_partition)) {
|
||||
_abort(UPDATE_ERROR_READ);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(esp_ota_set_boot_partition(_partition)){
|
||||
_abort(UPDATE_ERROR_ACTIVATE);
|
||||
return false;
|
||||
}
|
||||
_reset();
|
||||
return true;
|
||||
} else if(_command == U_SPIFFS) {
|
||||
_reset();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateClass::setMD5(const char * expected_md5){
|
||||
if(strlen(expected_md5) != 32)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_target_md5 = expected_md5;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UpdateClass::end(bool evenIfRemaining){
|
||||
if(hasError() || _size == 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!isFinished() && !evenIfRemaining){
|
||||
log_e("premature end: res:%u, pos:%u/%u\n", getError(), progress(), _size);
|
||||
_abort(UPDATE_ERROR_ABORT);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(evenIfRemaining) {
|
||||
if(_bufferLen > 0) {
|
||||
_writeBuffer();
|
||||
}
|
||||
_size = progress();
|
||||
}
|
||||
|
||||
_md5.calculate();
|
||||
if(_target_md5.length()) {
|
||||
if(_target_md5 != _md5.toString()){
|
||||
_abort(UPDATE_ERROR_MD5);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return _verifyEnd();
|
||||
}
|
||||
|
||||
size_t UpdateClass::write(uint8_t *data, size_t len) {
|
||||
if(hasError() || !isRunning()){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(len > remaining()){
|
||||
_abort(UPDATE_ERROR_SPACE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t left = len;
|
||||
|
||||
while((_bufferLen + left) > SPI_FLASH_SEC_SIZE) {
|
||||
size_t toBuff = SPI_FLASH_SEC_SIZE - _bufferLen;
|
||||
memcpy(_buffer + _bufferLen, data + (len - left), toBuff);
|
||||
_bufferLen += toBuff;
|
||||
if(!_writeBuffer()){
|
||||
return len - left;
|
||||
}
|
||||
left -= toBuff;
|
||||
}
|
||||
memcpy(_buffer + _bufferLen, data + (len - left), left);
|
||||
_bufferLen += left;
|
||||
if(_bufferLen == remaining()){
|
||||
if(!_writeBuffer()){
|
||||
return len - left;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t UpdateClass::writeStream(Stream &data) {
|
||||
data.setTimeout(RESPONSE_TIMEOUT_MS);
|
||||
size_t written = 0;
|
||||
size_t toRead = 0;
|
||||
if(hasError() || !isRunning())
|
||||
return 0;
|
||||
|
||||
if(!_verifyHeader(data.peek())) {
|
||||
_reset();
|
||||
return 0;
|
||||
}
|
||||
if (_progress_callback) {
|
||||
_progress_callback(0, _size);
|
||||
}
|
||||
|
||||
if(_ledPin != -1) {
|
||||
pinMode(_ledPin, OUTPUT);
|
||||
}
|
||||
|
||||
while(remaining()) {
|
||||
if(_ledPin != -1) {
|
||||
digitalWrite(_ledPin, _ledOn); // Switch LED on
|
||||
}
|
||||
size_t bytesToRead = SPI_FLASH_SEC_SIZE - _bufferLen;
|
||||
if(bytesToRead > remaining()) {
|
||||
bytesToRead = remaining();
|
||||
}
|
||||
|
||||
toRead = data.readBytes(_buffer + _bufferLen, bytesToRead);
|
||||
if(toRead == 0) { //Timeout
|
||||
delay(100);
|
||||
toRead = data.readBytes(_buffer + _bufferLen, bytesToRead);
|
||||
if(toRead == 0) { //Timeout
|
||||
_abort(UPDATE_ERROR_STREAM);
|
||||
return written;
|
||||
}
|
||||
}
|
||||
if(_ledPin != -1) {
|
||||
digitalWrite(_ledPin, !_ledOn); // Switch LED off
|
||||
}
|
||||
_bufferLen += toRead;
|
||||
if((_bufferLen == remaining() || _bufferLen == SPI_FLASH_SEC_SIZE) && !_writeBuffer())
|
||||
return written;
|
||||
written += toRead;
|
||||
if(_progress_callback) {
|
||||
_progress_callback(_progress, _size);
|
||||
}
|
||||
}
|
||||
if(_progress_callback) {
|
||||
_progress_callback(_size, _size);
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
void UpdateClass::printError(Stream &out){
|
||||
out.println(_err2str(_error));
|
||||
}
|
||||
|
||||
UpdateClass Update;
|
||||
Reference in new issue
Block a user