Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ffa48a6

Browse files
committedDec 13, 2022
first commit
0 parents  commit ffa48a6

22 files changed

+1338
-0
lines changed
 

‎.codespellrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[codespell]
2+
# In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here:
3+
ignore-words-list = ,
4+
check-filenames =
5+
check-hidden =
6+
skip = ./.git

‎.github/dependabot.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# See: https://docs.github.com/en/code-security/supply-chain-security/configuration-options-for-dependency-updates#about-the-dependabotyml-file
2+
version: 2
3+
4+
updates:
5+
# Configure check for outdated GitHub Actions actions in workflows.
6+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/dependabot/README.md
7+
# See: https://docs.github.com/en/code-security/supply-chain-security/keeping-your-actions-up-to-date-with-dependabot
8+
- package-ecosystem: github-actions
9+
directory: / # Check the repository's workflows under /.github/workflows/
10+
schedule:
11+
interval: daily
12+
labels:
13+
- "topic: infrastructure"

‎.github/workflows/arduino-lint.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Arduino Lint
2+
on:
3+
push:
4+
pull_request:
5+
# Scheduled trigger checks for breakage caused by new rules added to Arduino Lint
6+
schedule:
7+
# run every Saturday at 3 AM UTC
8+
- cron: "0 3 * * 6"
9+
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#workflow_dispatch
10+
workflow_dispatch:
11+
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#repository_dispatch
12+
repository_dispatch:
13+
14+
jobs:
15+
lint:
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@v3
21+
22+
- name: Arduino Lint
23+
uses: arduino/arduino-lint-action@v1
24+
with:
25+
official: true
26+
library-manager: update
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Compile Examples
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- ".github/workflows/compile-examples.yml"
7+
- "examples/**"
8+
- "src/**"
9+
push:
10+
paths:
11+
- ".github/workflows/compile-examples.yml"
12+
- "examples/**"
13+
- "src/**"
14+
# Scheduled trigger checks for breakage caused by changes to external resources (libraries, platforms)
15+
schedule:
16+
# run every Saturday at 3 AM UTC
17+
- cron: "0 3 * * 6"
18+
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#workflow_dispatch
19+
workflow_dispatch:
20+
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#repository_dispatch
21+
repository_dispatch:
22+
23+
jobs:
24+
build:
25+
runs-on: ubuntu-latest
26+
27+
env:
28+
SKETCHES_REPORTS_PATH: sketches-reports
29+
30+
strategy:
31+
fail-fast: false
32+
33+
matrix:
34+
board:
35+
- fqbn: "esp32:esp32:esp32"
36+
platforms: |
37+
- name: esp32:esp32
38+
source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
39+
libraries: ""
40+
41+
steps:
42+
- name: Checkout
43+
uses: actions/checkout@v3
44+
45+
- name: Compile examples
46+
uses: arduino/compile-sketches@main
47+
with:
48+
github-token: ${{ secrets.GITHUB_TOKEN }}
49+
fqbn: ${{ matrix.board.fqbn }}
50+
platforms: ${{ matrix.board.platforms }}
51+
libraries: |
52+
# Install the library from the local path.
53+
- source-path: ./
54+
${{ matrix.board.libraries }}
55+
sketch-paths: |
56+
- examples
57+
enable-deltas-report: true
58+
sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }}
59+
60+
- name: Save memory usage change report as artifact
61+
uses: actions/upload-artifact@v3
62+
with:
63+
name: ${{ env.SKETCHES_REPORTS_PATH }}
64+
path: ${{ env.SKETCHES_REPORTS_PATH }}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: Report Size Deltas
2+
3+
on:
4+
schedule:
5+
- cron: '*/5 * * * *'
6+
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#workflow_dispatch
7+
workflow_dispatch:
8+
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#repository_dispatch
9+
repository_dispatch:
10+
11+
jobs:
12+
report:
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
# See: https://github.com/arduino/actions/blob/master/libraries/report-size-deltas/README.md
17+
- name: Comment size deltas reports to PRs
18+
uses: arduino/report-size-deltas@main
19+
with:
20+
# The name of the workflow artifact created by the "Compile Examples" workflow
21+
sketches-reports-source: sketches-reports

‎.github/workflows/spell-check.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Spell Check
2+
3+
on:
4+
pull_request:
5+
push:
6+
schedule:
7+
# Run every Saturday at 3 AM UTC to catch new misspelling detections resulting from dictionary updates.
8+
- cron: "0 3 * * 6"
9+
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#workflow_dispatch
10+
workflow_dispatch:
11+
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#repository_dispatch
12+
repository_dispatch:
13+
14+
jobs:
15+
spellcheck:
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Checkout repository
20+
uses: actions/checkout@v3
21+
22+
# See: https://github.com/codespell-project/actions-codespell/blob/master/README.md
23+
- name: Spell check
24+
uses: codespell-project/actions-codespell@master

‎.github/workflows/sync-labels.yml

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/sync-labels.md
2+
name: Sync Labels
3+
4+
# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows
5+
on:
6+
push:
7+
paths:
8+
- ".github/workflows/sync-labels.ya?ml"
9+
- ".github/label-configuration-files/*.ya?ml"
10+
pull_request:
11+
paths:
12+
- ".github/workflows/sync-labels.ya?ml"
13+
- ".github/label-configuration-files/*.ya?ml"
14+
schedule:
15+
# Run daily at 8 AM UTC to sync with changes to shared label configurations.
16+
- cron: "0 8 * * *"
17+
workflow_dispatch:
18+
repository_dispatch:
19+
20+
env:
21+
CONFIGURATIONS_FOLDER: .github/label-configuration-files
22+
CONFIGURATIONS_ARTIFACT: label-configuration-files
23+
24+
jobs:
25+
check:
26+
runs-on: ubuntu-latest
27+
28+
steps:
29+
- name: Checkout repository
30+
uses: actions/checkout@v3
31+
32+
- name: Download JSON schema for labels configuration file
33+
id: download-schema
34+
uses: carlosperate/download-file-action@v2
35+
with:
36+
file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json
37+
location: ${{ runner.temp }}/label-configuration-schema
38+
39+
- name: Install JSON schema validator
40+
run: |
41+
sudo npm install \
42+
--global \
43+
ajv-cli \
44+
ajv-formats
45+
46+
- name: Validate local labels configuration
47+
run: |
48+
# See: https://github.com/ajv-validator/ajv-cli#readme
49+
ajv validate \
50+
--all-errors \
51+
-c ajv-formats \
52+
-s "${{ steps.download-schema.outputs.file-path }}" \
53+
-d "${{ env.CONFIGURATIONS_FOLDER }}/*.{yml,yaml}"
54+
55+
download:
56+
needs: check
57+
runs-on: ubuntu-latest
58+
59+
strategy:
60+
matrix:
61+
filename:
62+
# Filenames of the shared configurations to apply to the repository in addition to the local configuration.
63+
# https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/sync-labels
64+
- universal.yml
65+
66+
steps:
67+
- name: Download
68+
uses: carlosperate/download-file-action@v2
69+
with:
70+
file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }}
71+
72+
- name: Pass configuration files to next job via workflow artifact
73+
uses: actions/upload-artifact@v3
74+
with:
75+
path: |
76+
*.yaml
77+
*.yml
78+
if-no-files-found: error
79+
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
80+
81+
sync:
82+
needs: download
83+
runs-on: ubuntu-latest
84+
85+
steps:
86+
- name: Set environment variables
87+
run: |
88+
# See: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
89+
echo "MERGED_CONFIGURATION_PATH=${{ runner.temp }}/labels.yml" >> "$GITHUB_ENV"
90+
91+
- name: Determine whether to dry run
92+
id: dry-run
93+
if: >
94+
github.event_name == 'pull_request' ||
95+
(
96+
(
97+
github.event_name == 'push' ||
98+
github.event_name == 'workflow_dispatch'
99+
) &&
100+
github.ref != format('refs/heads/{0}', github.event.repository.default_branch)
101+
)
102+
run: |
103+
# Use of this flag in the github-label-sync command will cause it to only check the validity of the
104+
# configuration.
105+
echo "::set-output name=flag::--dry-run"
106+
107+
- name: Checkout repository
108+
uses: actions/checkout@v3
109+
110+
- name: Download configuration files artifact
111+
uses: actions/download-artifact@v3
112+
with:
113+
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
114+
path: ${{ env.CONFIGURATIONS_FOLDER }}
115+
116+
- name: Remove unneeded artifact
117+
uses: geekyeggo/delete-artifact@v2
118+
with:
119+
name: ${{ env.CONFIGURATIONS_ARTIFACT }}
120+
121+
- name: Merge label configuration files
122+
run: |
123+
# Merge all configuration files
124+
shopt -s extglob
125+
cat "${{ env.CONFIGURATIONS_FOLDER }}"/*.@(yml|yaml) > "${{ env.MERGED_CONFIGURATION_PATH }}"
126+
127+
- name: Install github-label-sync
128+
run: sudo npm install --global github-label-sync
129+
130+
- name: Sync labels
131+
env:
132+
GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
133+
run: |
134+
# See: https://github.com/Financial-Times/github-label-sync
135+
github-label-sync \
136+
--labels "${{ env.MERGED_CONFIGURATION_PATH }}" \
137+
${{ steps.dry-run.outputs.flag }} \
138+
${{ github.repository }}

‎README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Arduino_ESP_OTA
2+
====================
3+
4+
[![Compile Examples](https://github.com/bcmi-labs/Arduino_ESP_OTA/workflows/Compile%20Examples/badge.svg)](https://github.com/bcmi-labs/Arduino_ESP_OTA/actions?workflow=Compile+Examples)
5+
[![Arduino Lint](https://github.com/bcmi-labs/Arduino_ESP_OTA/workflows/Arduino%20Lint/badge.svg)](https://github.com/bcmi-labs/Arduino_ESP_OTA/actions?workflow=Arduino+Lint)
6+
[![Spell Check](https://github.com/bcmi-labs/Arduino_ESP_OTA/workflows/Spell%20Check/badge.svg)](https://github.com/bcmi-labs/Arduino_ESP_OTA/actions?workflow=Spell+Check)
7+
8+
This library allows OTA (Over-The-Air) firmware updates for ESP boards. OTA binaries are downloaded via WiFi and stored in the OTA flash partition. After a reset the ESP bootloader performs the firmware update.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Blink for LOLIN32 ESP32 board
3+
*
4+
* This sketch can be used to generate an example binary that can be uploaded to ESP32 via OTA.
5+
* It needs to be used together with OTA.ino
6+
*
7+
* Steps to test OTA on ESP32:
8+
* 1) Upload this sketch or any other sketch (this one will blink LOLIN32 blue LED).
9+
* 2) In the IDE select: Sketch -> Export compiled Binary
10+
* 3) Upload the exported binary to a server
11+
* 4) Open the related OTA.ino sketch and eventually update the OTA_FILE_LOCATION
12+
* 5) Upload the sketch OTA.ino to perform OTA
13+
*/
14+
15+
void setup() {
16+
// initialize digital pin 5 as an output.
17+
pinMode(5, OUTPUT);
18+
}
19+
20+
void loop() {
21+
digitalWrite(5, HIGH);
22+
delay(1000);
23+
digitalWrite(5, LOW);
24+
delay(1000);
25+
}

‎examples/OTA/OTA.ino

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* This example demonstrates how to use to update the firmware using Arduino_ESP_OTA library
3+
*
4+
* Steps:
5+
* 1) Create a sketch for your ESP board and verify
6+
* that it both compiles and works.
7+
* 2) In the IDE select: Sketch -> Export compiled Binary.
8+
* 3) Create an OTA update file utilising the tools 'lzss.py' and 'bin2ota.py' stored in
9+
* https://github.com/arduino-libraries/ArduinoIoTCloud/tree/master/extras/tools .
10+
* A) ./lzss.py --encode SKETCH.bin SKETCH.lzss
11+
* B) ./bin2ota.py ESP SKETCH.lzss SKETCH.ota
12+
* 4) Upload the OTA file to a network reachable location, e.g. LOLIN_32_Blink.ino.ota
13+
* has been uploaded to: http://downloads.arduino.cc/ota/LOLIN_32_Blink.ino.ota
14+
* 5) Verify if a custom ca_cert is needed by default Amazon root CA are used
15+
* https://www.amazontrust.com/repository/
16+
* 6) Perform an OTA update via steps outlined below.
17+
*/
18+
19+
/******************************************************************************
20+
* INCLUDE
21+
******************************************************************************/
22+
23+
#include <Arduino_ESP32_OTA.h>
24+
25+
#include <WiFi.h>
26+
27+
#include "arduino_secrets.h"
28+
29+
#include "root_ca.h"
30+
31+
/******************************************************************************
32+
* CONSTANT
33+
******************************************************************************/
34+
35+
/* Please enter your sensitive data in the Secret tab/arduino_secrets.h */
36+
static char const SSID[] = SECRET_SSID; /* your network SSID (name) */
37+
static char const PASS[] = SECRET_PASS; /* your network password (use for WPA, or use as key for WEP) */
38+
39+
static char const OTA_FILE_LOCATION[] = "https://downloads.arduino.cc/ota/LOLIN_32_Blink.ino.ota";
40+
41+
/******************************************************************************
42+
* SETUP/LOOP
43+
******************************************************************************/
44+
45+
void setup()
46+
{
47+
Serial.begin(9600);
48+
while (!Serial) {}
49+
50+
int status = WL_IDLE_STATUS;
51+
while (WiFi.status() != WL_CONNECTED)
52+
{
53+
Serial.print ("Attempting to connect to '");
54+
Serial.print (SSID);
55+
Serial.println("'");
56+
WiFi.begin(SSID, PASS);
57+
delay(2000);
58+
}
59+
Serial.print ("You're connected to '");
60+
Serial.print (WiFi.SSID());
61+
Serial.println("'");
62+
63+
Arduino_ESP32_OTA ota;
64+
Arduino_ESP32_OTA::Error ota_err = Arduino_ESP32_OTA::Error::None;
65+
66+
/* Configure custom Root CA */
67+
ota.setCACert(root_ca);
68+
69+
Serial.println("Initializing OTA storage");
70+
if ((ota_err = ota.begin()) != Arduino_ESP32_OTA::Error::None)
71+
{
72+
Serial.print ("Arduino_ESP_OTA::begin() failed with error code ");
73+
Serial.println((int)ota_err);
74+
return;
75+
}
76+
77+
78+
Serial.println("Starting download to flash ...");
79+
int const ota_download = ota.download(OTA_FILE_LOCATION);
80+
if (ota_download <= 0)
81+
{
82+
Serial.print ("Arduino_ESP_OTA::download failed with error code ");
83+
Serial.println(ota_download);
84+
return;
85+
}
86+
Serial.print (ota_download);
87+
Serial.println(" bytes stored.");
88+
89+
90+
Serial.println("Verify update integrity and apply ...");
91+
if ((ota_err = ota.update()) != Arduino_ESP32_OTA::Error::None)
92+
{
93+
Serial.print ("ota.update() failed with error code ");
94+
Serial.println((int)ota_err);
95+
return;
96+
}
97+
98+
Serial.println("Performing a reset after which the bootloader will start the new firmware.");
99+
Serial.println("Hint: LOLIN32 will blink Blue.");
100+
delay(1000); /* Make sure the serial message gets out before the reset. */
101+
ota.reset();
102+
}
103+
104+
void loop()
105+
{
106+
107+
}

‎examples/OTA/arduino_secrets.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define SECRET_SSID ""
2+
#define SECRET_PASS ""

‎examples/OTA/root_ca.h

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
const char* root_ca = \
2+
/* Baltimore CyberTrust Root */
3+
"-----BEGIN CERTIFICATE-----\n" \
4+
"MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE\n" \
5+
"ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li\n" \
6+
"ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC\n" \
7+
"SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs\n" \
8+
"dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME\n" \
9+
"uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB\n" \
10+
"UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C\n" \
11+
"G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9\n" \
12+
"XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr\n" \
13+
"l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI\n" \
14+
"VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB\n" \
15+
"BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh\n" \
16+
"cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5\n" \
17+
"hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa\n" \
18+
"Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H\n" \
19+
"RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\n" \
20+
"-----END CERTIFICATE-----\n" \
21+
/* Amazon Root CA 1 */
22+
"-----BEGIN CERTIFICATE-----\n" \
23+
"MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD\n" \
24+
"VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1\n" \
25+
"MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv\n" \
26+
"bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" \
27+
"ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH\n" \
28+
"FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ\n" \
29+
"gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t\n" \
30+
"dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce\n" \
31+
"VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB\n" \
32+
"/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3\n" \
33+
"DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM\n" \
34+
"CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy\n" \
35+
"8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa\n" \
36+
"2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2\n" \
37+
"xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5\n" \
38+
"-----END CERTIFICATE-----\n" \
39+
/* Amazon Root CA 2 */
40+
"-----BEGIN CERTIFICATE-----\n" \
41+
"MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD\n" \
42+
"VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1\n" \
43+
"MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv\n" \
44+
"bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC\n" \
45+
"ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4\n" \
46+
"kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp\n" \
47+
"N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9\n" \
48+
"AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd\n" \
49+
"fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx\n" \
50+
"kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS\n" \
51+
"btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0\n" \
52+
"Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN\n" \
53+
"c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+\n" \
54+
"3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw\n" \
55+
"DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA\n" \
56+
"A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY\n" \
57+
"+gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE\n" \
58+
"YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW\n" \
59+
"xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ\n" \
60+
"gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW\n" \
61+
"aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV\n" \
62+
"Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3\n" \
63+
"KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi\n" \
64+
"JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=\n" \
65+
"-----END CERTIFICATE-----\n" \
66+
/* Amazon Root CA 3 */
67+
"-----BEGIN CERTIFICATE-----\n" \
68+
"MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG\n" \
69+
"EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy\n" \
70+
"NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ\n" \
71+
"MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB\n" \
72+
"f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr\n" \
73+
"Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43\n" \
74+
"rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc\n" \
75+
"eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==\n" \
76+
"-----END CERTIFICATE-----\n" \
77+
/* Amazon Root CA 4 */
78+
"-----BEGIN CERTIFICATE-----\n" \
79+
"MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG\n" \
80+
"EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy\n" \
81+
"NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ\n" \
82+
"MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN\n" \
83+
"/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri\n" \
84+
"83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\n" \
85+
"HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA\n" \
86+
"MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1\n" \
87+
"AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==\n" \
88+
"-----END CERTIFICATE-----\n";

‎keywords.txt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#######################################
2+
# Syntax Coloring Map For Arduino_ESP_OTA
3+
#######################################
4+
5+
#######################################
6+
# Class (KEYWORD1)
7+
#######################################
8+
9+
Arduino_ESP_OTA KEYWORD1
10+
Error KEYWORD1
11+
12+
#######################################
13+
# Methods and Functions (KEYWORD2)
14+
#######################################
15+
16+
begin KEYWORD2
17+
update KEYWORD2
18+
reset KEYWORD2
19+
download KEYWORD2
20+
21+
#######################################
22+
# Constants (LITERAL1)
23+
#######################################
24+
25+
None LITERAL1
26+
NoOtaStorage LITERAL1
27+
OtaStorageInit LITERAL1
28+
OtaStorageEnd LITERAL1
29+
UrlParseError LITERAL1
30+
ServerConnectError LITERAL1
31+
HttpHeaderError LITERAL1
32+
ParseHttpHeader LITERAL1
33+
OtaHeaderLength LITERAL1
34+
OtaHeaderCrc LITERAL1
35+
OtaHeaterMagicNumber LITERAL1
36+
OtaDownload LITERAL1

‎library.properties

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name=Arduino_ESP_OTA
2+
version=0.0.1
3+
author=Arduino
4+
maintainer=Arduino <info@arduino.cc>
5+
sentence=Firmware update for ESP32.
6+
paragraph=This library allows performing a firmware update on ESP32.
7+
category=Communication
8+
url=
9+
architectures=esp32
10+
includes=Arduino_ESP_OTA.h

‎src/Arduino_ESP32_OTA.cpp

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
/*
2+
This file is part of Arduino_ESP_OTA.
3+
4+
Copyright 2022 ARDUINO SA (http://www.arduino.cc/)
5+
6+
This software is released under the GNU General Public License version 3,
7+
which covers the main part of arduino-cli.
8+
The terms of this license can be found at:
9+
https://www.gnu.org/licenses/gpl-3.0.en.html
10+
11+
You can be released from the requirements of the above licenses by purchasing
12+
a commercial license. Buying such a license is mandatory if you want to modify or
13+
otherwise use the software for commercial activities involving the Arduino
14+
software without disclosing the source code of your own applications. To purchase
15+
a commercial license, send an email to license@arduino.cc.
16+
*/
17+
18+
/******************************************************************************
19+
INCLUDE
20+
******************************************************************************/
21+
22+
#include <Update.h>
23+
#include "Arduino_ESP32_OTA.h"
24+
#include "tls/amazon_root_ca.h"
25+
#include "decompress/lzss.h"
26+
#include "decompress/utility.h"
27+
#include "esp_ota_ops.h"
28+
29+
/* Used to bind local module function to actual class instance */
30+
static Arduino_ESP32_OTA * _esp_ota_obj_ptr = 0;
31+
32+
/******************************************************************************
33+
LOCAL MODULE FUNCTIONS
34+
******************************************************************************/
35+
36+
static uint8_t read_byte() {
37+
if(_esp_ota_obj_ptr) {
38+
return _esp_ota_obj_ptr->read_byte_from_network();
39+
}
40+
return -1;
41+
}
42+
43+
static void write_byte(uint8_t data) {
44+
if(_esp_ota_obj_ptr) {
45+
_esp_ota_obj_ptr->write_byte_to_flash(data);
46+
}
47+
}
48+
49+
/******************************************************************************
50+
CTOR/DTOR
51+
******************************************************************************/
52+
53+
Arduino_ESP32_OTA::Arduino_ESP32_OTA()
54+
:_client{nullptr}
55+
,_ota_header{0}
56+
,_ota_size(0)
57+
,_crc32(0)
58+
,_ca_cert{amazon_root_ca}
59+
{
60+
61+
}
62+
63+
/******************************************************************************
64+
PUBLIC MEMBER FUNCTIONS
65+
******************************************************************************/
66+
67+
Arduino_ESP32_OTA::Error Arduino_ESP32_OTA::begin()
68+
{
69+
_esp_ota_obj_ptr = this;
70+
71+
/* ... initialize CRC ... */
72+
_crc32 = 0xFFFFFFFF;
73+
74+
if(!Update.begin(UPDATE_SIZE_UNKNOWN)) {
75+
DEBUG_ERROR("%s: failed to initialize flash update", __FUNCTION__);
76+
return Error::OtaStorageInit;
77+
}
78+
return Error::None;
79+
}
80+
81+
void Arduino_ESP32_OTA::setCACert (const char *rootCA)
82+
{
83+
if(rootCA != nullptr) {
84+
_ca_cert = rootCA;
85+
}
86+
}
87+
88+
uint8_t Arduino_ESP32_OTA::read_byte_from_network()
89+
{
90+
bool is_http_data_timeout = false;
91+
for(unsigned long const start = millis();;)
92+
{
93+
is_http_data_timeout = (millis() - start) > ARDUINO_ESP_OTA_BINARY_BYTE_RECEIVE_TIMEOUT_ms;
94+
if (is_http_data_timeout) {
95+
DEBUG_ERROR("%s: timeout waiting data", __FUNCTION__);
96+
return -1;
97+
}
98+
if (_client->available()) {
99+
const uint8_t data = _client->read();
100+
_crc32 = crc_update(_crc32, &data, 1);
101+
return data;
102+
}
103+
}
104+
}
105+
106+
void Arduino_ESP32_OTA::write_byte_to_flash(uint8_t data)
107+
{
108+
Update.write(&data, 1);
109+
}
110+
111+
int Arduino_ESP32_OTA::download(const char * ota_url)
112+
{
113+
URI url(ota_url);
114+
int port = 0;
115+
int err = -1;
116+
117+
if (url.protocol_ == "http") {
118+
_client = new WiFiClient();
119+
port = 80;
120+
} else if (url.protocol_ == "https") {
121+
_client = new WiFiClientSecure();
122+
static_cast<WiFiClientSecure*>(_client)->setCACert(_ca_cert);
123+
port = 443;
124+
} else {
125+
DEBUG_ERROR("%s: Failed to parse OTA URL %s", __FUNCTION__, ota_url);
126+
return static_cast<int>(Error::UrlParseError);
127+
}
128+
129+
if (!_client->connect(url.host_.c_str(), port))
130+
{
131+
DEBUG_ERROR("%s: Connection failure with OTA storage server %s", __FUNCTION__, url.host_.c_str());
132+
return static_cast<int>(Error::ServerConnectError);
133+
}
134+
135+
_client->println(String("GET ") + url.path_.c_str() + " HTTP/1.1");
136+
_client->println(String("Host: ") + url.host_.c_str());
137+
_client->println("Connection: close");
138+
_client->println();
139+
140+
/* Receive HTTP header. */
141+
String http_header;
142+
bool is_header_complete = false,
143+
is_http_header_timeout = false;
144+
for (unsigned long const start = millis(); !is_header_complete;)
145+
{
146+
is_http_header_timeout = (millis() - start) > ARDUINO_ESP_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms;
147+
if (is_http_header_timeout) break;
148+
149+
if (_client->available())
150+
{
151+
char const c = _client->read();
152+
153+
http_header += c;
154+
if (http_header.endsWith("\r\n\r\n"))
155+
is_header_complete = true;
156+
}
157+
}
158+
159+
if (!is_header_complete)
160+
{
161+
DEBUG_ERROR("%s: Error receiving HTTP header %s", __FUNCTION__, is_http_header_timeout ? "(timeout)":"");
162+
return static_cast<int>(Error::HttpHeaderError);
163+
}
164+
165+
/* TODO check http header 200 or else*/
166+
167+
/* Extract concent length from HTTP header. A typical entry looks like
168+
* "Content-Length: 123456"
169+
*/
170+
char const * content_length_ptr = strstr(http_header.c_str(), "Content-Length");
171+
if (!content_length_ptr)
172+
{
173+
DEBUG_ERROR("%s: Failure to extract content length from http header", __FUNCTION__);
174+
return static_cast<int>(Error::ParseHttpHeader);
175+
}
176+
/* Find start of numerical value. */
177+
char * ptr = const_cast<char *>(content_length_ptr);
178+
for (; (*ptr != '\0') && !isDigit(*ptr); ptr++) { }
179+
/* Extract numerical value. */
180+
String content_length_str;
181+
for (; isDigit(*ptr); ptr++) content_length_str += *ptr;
182+
int const content_length_val = atoi(content_length_str.c_str());
183+
DEBUG_VERBOSE("%s: Length of OTA binary according to HTTP header = %d bytes", __FUNCTION__, content_length_val);
184+
185+
/* Read the OTA header ... */
186+
_client->read(_ota_header.buf, sizeof(OtaHeader));
187+
188+
/* ... and check first length ... */
189+
if (_ota_header.header.len != (content_length_val - sizeof(_ota_header.header.len) - sizeof(_ota_header.header.crc32))) {
190+
return static_cast<int>(Error::OtaHeaderLength);
191+
}
192+
193+
if (_ota_header.header.magic_number != 0x00000000)
194+
{
195+
return static_cast<int>(Error::OtaHeaterMagicNumber);
196+
}
197+
198+
/* ... start CRC32 from OTA MAGIC ... */
199+
_crc32 = crc_update(_crc32, &_ota_header.header.magic_number, 12);
200+
201+
/* Download and decode OTA file */
202+
_ota_size = lzss_download(read_byte, write_byte, content_length_val - sizeof(_ota_header));
203+
204+
if(_ota_size <= content_length_val - sizeof(_ota_header))
205+
{
206+
return static_cast<int>(Error::OtaDownload);
207+
}
208+
209+
return _ota_size;
210+
}
211+
212+
Arduino_ESP32_OTA::Error Arduino_ESP32_OTA::update()
213+
{
214+
/* ... then finalise ... */
215+
_crc32 ^= 0xFFFFFFFF;
216+
217+
if(_crc32 != _ota_header.header.crc32) {
218+
DEBUG_ERROR("%s: CRC32 mismatch", __FUNCTION__);
219+
return Error::OtaHeaderCrc;
220+
}
221+
222+
if (!Update.end(true)) {
223+
DEBUG_ERROR("%s: Failure to apply OTA update", __FUNCTION__);
224+
return Error::OtaStorageEnd;
225+
}
226+
227+
return Error::None;
228+
}
229+
230+
void Arduino_ESP32_OTA::reset()
231+
{
232+
ESP.restart();
233+
}

‎src/Arduino_ESP32_OTA.h

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
This file is part of Arduino_ESP_OTA.
3+
4+
Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
5+
6+
This software is released under the GNU General Public License version 3,
7+
which covers the main part of arduino-cli.
8+
The terms of this license can be found at:
9+
https://www.gnu.org/licenses/gpl-3.0.en.html
10+
11+
You can be released from the requirements of the above licenses by purchasing
12+
a commercial license. Buying such a license is mandatory if you want to modify or
13+
otherwise use the software for commercial activities involving the Arduino
14+
software without disclosing the source code of your own applications. To purchase
15+
a commercial license, send an email to license@arduino.cc.
16+
*/
17+
18+
#ifndef ARDUINO_ESP32_OTA_H_
19+
#define ARDUINO_ESP32_OTA_H_
20+
21+
/******************************************************************************
22+
* INCLUDE
23+
******************************************************************************/
24+
25+
#include <Arduino_DebugUtils.h>
26+
#include <WiFiClientSecure.h>
27+
#include "decompress/utility.h"
28+
29+
/******************************************************************************
30+
CONSTANTS
31+
******************************************************************************/
32+
33+
static uint32_t const ARDUINO_ESP_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms = 10000;
34+
static uint32_t const ARDUINO_ESP_OTA_BINARY_BYTE_RECEIVE_TIMEOUT_ms = 2000;
35+
36+
/******************************************************************************
37+
* TYPEDEF
38+
******************************************************************************/
39+
40+
typedef uint8_t(*ArduinoEspOtaReadByteFuncPointer)(void);
41+
typedef void(*ArduinoEspOtaWriteByteFuncPointer)(uint8_t);
42+
43+
/******************************************************************************
44+
* CLASS DECLARATION
45+
******************************************************************************/
46+
47+
class Arduino_ESP32_OTA
48+
{
49+
50+
public:
51+
52+
enum class Error : int
53+
{
54+
None = 0,
55+
NoOtaStorage = -2,
56+
OtaStorageInit = -3,
57+
OtaStorageEnd = -4,
58+
UrlParseError = -5,
59+
ServerConnectError = -6,
60+
HttpHeaderError = -7,
61+
ParseHttpHeader = -8,
62+
OtaHeaderLength = -9,
63+
OtaHeaderCrc = -10,
64+
OtaHeaterMagicNumber = -11,
65+
OtaDownload = -12,
66+
};
67+
68+
Arduino_ESP32_OTA();
69+
virtual ~Arduino_ESP32_OTA() { }
70+
71+
Arduino_ESP32_OTA::Error begin();
72+
void setCACert (const char *rootCA);
73+
int download(const char * ota_url);
74+
uint8_t read_byte_from_network();
75+
void write_byte_to_flash(uint8_t data);
76+
Arduino_ESP32_OTA::Error update();
77+
void reset();
78+
79+
private:
80+
81+
Client * _client;
82+
OtaHeader _ota_header;
83+
size_t _ota_size;
84+
uint32_t _crc32;
85+
const char * _ca_cert;
86+
};
87+
88+
#endif /* ARDUINO_ESP32_OTA_H_ */

‎src/Arduino_ESP_OTA.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
This file is part of Arduino_ESP_OTA.
3+
4+
Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
5+
6+
This software is released under the GNU General Public License version 3,
7+
which covers the main part of arduino-cli.
8+
The terms of this license can be found at:
9+
https://www.gnu.org/licenses/gpl-3.0.en.html
10+
11+
You can be released from the requirements of the above licenses by purchasing
12+
a commercial license. Buying such a license is mandatory if you want to modify or
13+
otherwise use the software for commercial activities involving the Arduino
14+
software without disclosing the source code of your own applications. To purchase
15+
a commercial license, send an email to license@arduino.cc.
16+
*/
17+
18+
#ifndef ARDUINO_ESP_OTA_H_
19+
#define ARDUINO_ESP_OTA_H_
20+
21+
#include "Arduino_ESP32_OTA.h"
22+
23+
#endif

‎src/decompress/lzss.cpp

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/* Original code: https://oku.edu.mie-u.ac.jp/~okumura/compression/lzss.c */
2+
3+
/**************************************************************************************
4+
INCLUDE
5+
**************************************************************************************/
6+
7+
#include "lzss.h"
8+
9+
/**************************************************************************************
10+
DEFINE
11+
**************************************************************************************/
12+
13+
#define EI 11 /* typically 10..13 */
14+
#define EJ 4 /* typically 4..5 */
15+
#define P 1 /* If match length <= P then output one character */
16+
#define N (1 << EI) /* buffer size */
17+
#define L ((1 << EJ) + 1) /* lookahead buffer size */
18+
19+
#define LZSS_EOF (-1)
20+
21+
/**************************************************************************************
22+
GLOBAL VARIABLES
23+
**************************************************************************************/
24+
25+
static size_t LZSS_FILE_SIZE = 0;
26+
static ArduinoEspOtaReadByteFuncPointer read_byte_fptr = 0;
27+
static ArduinoEspOtaWriteByteFuncPointer write_byte_fptr = 0;
28+
29+
int bit_buffer = 0, bit_mask = 128;
30+
unsigned char buffer[N * 2];
31+
32+
static size_t bytes_written_fputc = 0;
33+
34+
/**************************************************************************************
35+
PRIVATE FUNCTIONS
36+
**************************************************************************************/
37+
38+
void lzss_fputc(int const c)
39+
{
40+
write_byte_fptr((uint8_t)c);
41+
42+
/* write byte callback */
43+
bytes_written_fputc++;
44+
}
45+
46+
int lzss_fgetc()
47+
{
48+
static size_t bytes_read_fgetc = 0;
49+
50+
/* lzss_file_size is set within SSUBoot:main
51+
* and contains the size of the LZSS file. Once
52+
* all those bytes have been read its time to return
53+
* LZSS_EOF in order to signal that the end of
54+
* the file has been reached.
55+
*/
56+
if (bytes_read_fgetc == LZSS_FILE_SIZE)
57+
return LZSS_EOF;
58+
59+
/* read byte callback */
60+
uint8_t const c = read_byte_fptr();
61+
bytes_read_fgetc++;
62+
63+
return c;
64+
}
65+
66+
/**************************************************************************************
67+
LZSS FUNCTIONS
68+
**************************************************************************************/
69+
70+
void putbit1(void)
71+
{
72+
bit_buffer |= bit_mask;
73+
if ((bit_mask >>= 1) == 0) {
74+
lzss_fputc(bit_buffer);
75+
bit_buffer = 0; bit_mask = 128;
76+
}
77+
}
78+
79+
void putbit0(void)
80+
{
81+
if ((bit_mask >>= 1) == 0) {
82+
lzss_fputc(bit_buffer);
83+
bit_buffer = 0; bit_mask = 128;
84+
}
85+
}
86+
87+
void output1(int c)
88+
{
89+
int mask;
90+
91+
putbit1();
92+
mask = 256;
93+
while (mask >>= 1) {
94+
if (c & mask) putbit1();
95+
else putbit0();
96+
}
97+
}
98+
99+
void output2(int x, int y)
100+
{
101+
int mask;
102+
103+
putbit0();
104+
mask = N;
105+
while (mask >>= 1) {
106+
if (x & mask) putbit1();
107+
else putbit0();
108+
}
109+
mask = (1 << EJ);
110+
while (mask >>= 1) {
111+
if (y & mask) putbit1();
112+
else putbit0();
113+
}
114+
}
115+
116+
int getbit(int n) /* get n bits */
117+
{
118+
int i, x;
119+
static int buf, mask = 0;
120+
121+
x = 0;
122+
for (i = 0; i < n; i++) {
123+
if (mask == 0) {
124+
if ((buf = lzss_fgetc()) == LZSS_EOF) return LZSS_EOF;
125+
mask = 128;
126+
}
127+
x <<= 1;
128+
if (buf & mask) x++;
129+
mask >>= 1;
130+
}
131+
return x;
132+
}
133+
134+
void lzss_decode(void)
135+
{
136+
int i, j, k, r, c;
137+
138+
for (i = 0; i < N - L; i++) buffer[i] = ' ';
139+
r = N - L;
140+
while ((c = getbit(1)) != LZSS_EOF) {
141+
if (c) {
142+
if ((c = getbit(8)) == LZSS_EOF) break;
143+
lzss_fputc(c);
144+
buffer[r++] = c; r &= (N - 1);
145+
} else {
146+
if ((i = getbit(EI)) == LZSS_EOF) break;
147+
if ((j = getbit(EJ)) == LZSS_EOF) break;
148+
for (k = 0; k <= j + 1; k++) {
149+
c = buffer[(i + k) & (N - 1)];
150+
lzss_fputc(c);
151+
buffer[r++] = c; r &= (N - 1);
152+
}
153+
}
154+
}
155+
}
156+
157+
/**************************************************************************************
158+
PUBLIC FUNCTIONS
159+
**************************************************************************************/
160+
161+
int lzss_download(ArduinoEspOtaReadByteFuncPointer read_byte, ArduinoEspOtaWriteByteFuncPointer write_byte, size_t const lzss_file_size)
162+
{
163+
read_byte_fptr = read_byte;
164+
write_byte_fptr = write_byte;
165+
LZSS_FILE_SIZE = lzss_file_size;
166+
lzss_decode();
167+
return bytes_written_fputc;
168+
}

‎src/decompress/lzss.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef SSU_LZSS_H_
2+
#define SSU_LZSS_H_
3+
4+
/**************************************************************************************
5+
INCLUDE
6+
**************************************************************************************/
7+
8+
#include "Arduino_ESP32_OTA.h"
9+
10+
/**************************************************************************************
11+
FUNCTION DEFINITION
12+
**************************************************************************************/
13+
14+
int lzss_download(ArduinoEspOtaReadByteFuncPointer read_byte, ArduinoEspOtaWriteByteFuncPointer write_byte, size_t const lzss_file_size);
15+
16+
#endif /* SSU_LZSS_H_ */

‎src/decompress/utility.cpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
Copyright (c) 2017 Arduino LLC. All right reserved.
3+
4+
This library is free software; you can redistribute it and/or
5+
modify it under the terms of the GNU Lesser General Public
6+
License as published by the Free Software Foundation; either
7+
version 2.1 of the License, or (at your option) any later version.
8+
9+
This library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
See the GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with this library; if not, write to the Free Software
16+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*/
18+
19+
/**************************************************************************************
20+
INCLUDE
21+
**************************************************************************************/
22+
23+
#include "utility.h"
24+
25+
/**************************************************************************************
26+
CONST
27+
**************************************************************************************/
28+
29+
static const uint32_t crc_table[256] =
30+
{
31+
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
32+
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
33+
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
34+
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
35+
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
36+
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
37+
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
38+
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
39+
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
40+
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
41+
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
42+
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
43+
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
44+
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
45+
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
46+
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
47+
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
48+
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
49+
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
50+
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
51+
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
52+
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
53+
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
54+
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
55+
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
56+
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
57+
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
58+
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
59+
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
60+
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
61+
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
62+
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
63+
};
64+
65+
/**************************************************************************************
66+
FUNCTIONS
67+
**************************************************************************************/
68+
69+
uint32_t crc_update(uint32_t crc, const void * data, size_t data_len)
70+
{
71+
const unsigned char *d = (const unsigned char *)data;
72+
unsigned int tbl_idx;
73+
74+
while (data_len--) {
75+
tbl_idx = (crc ^ *d) & 0xff;
76+
crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff;
77+
d++;
78+
}
79+
80+
return crc & 0xffffffff;
81+
}
82+
83+
/* Original code: http://stackoverflow.com/questions/2616011/easy-way-to-parse-a-url-in-c-cross-platform */
84+
using namespace std;
85+
86+
// ctors, copy, equality, ...
87+
// TODO: change me into something embedded friendly (this function adds ~100KB to flash)
88+
void URI::parse(const string& url_s)
89+
{
90+
const string prot_end("://");
91+
string::const_iterator prot_i = search(url_s.begin(), url_s.end(),
92+
prot_end.begin(), prot_end.end());
93+
protocol_.reserve(distance(url_s.begin(), prot_i));
94+
transform(url_s.begin(), prot_i,
95+
back_inserter(protocol_),
96+
ptr_fun<int,int>(tolower)); // protocol is icase
97+
if( prot_i == url_s.end() )
98+
return;
99+
advance(prot_i, prot_end.length());
100+
string::const_iterator path_i = find(prot_i, url_s.end(), '/');
101+
host_.reserve(distance(prot_i, path_i));
102+
transform(prot_i, path_i,
103+
back_inserter(host_),
104+
ptr_fun<int,int>(tolower)); // host is icase
105+
string::const_iterator query_i = find(path_i, url_s.end(), '?');
106+
path_.assign(path_i, query_i);
107+
if( query_i != url_s.end() )
108+
++query_i;
109+
query_.assign(query_i, url_s.end());
110+
}

‎src/decompress/utility.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#ifndef ESP_OTA_UTILITY_H_
2+
#define ESP_OTA_UTILITY_H_
3+
4+
/**************************************************************************************
5+
INCLUDE
6+
**************************************************************************************/
7+
#include <string>
8+
#include <algorithm>
9+
#include <cctype>
10+
#include <functional>
11+
#include <iostream>
12+
13+
struct URI {
14+
public:
15+
URI(const std::string& url_s) {
16+
this->parse(url_s);
17+
}
18+
std::string protocol_, host_, path_, query_;
19+
private:
20+
void parse(const std::string& url_s);
21+
};
22+
23+
union HeaderVersion
24+
{
25+
struct __attribute__((packed))
26+
{
27+
uint32_t header_version : 6;
28+
uint32_t compression : 1;
29+
uint32_t signature : 1;
30+
uint32_t spare : 4;
31+
uint32_t payload_target : 4;
32+
uint32_t payload_major : 8;
33+
uint32_t payload_minor : 8;
34+
uint32_t payload_patch : 8;
35+
uint32_t payload_build_num : 24;
36+
} field;
37+
uint8_t buf[sizeof(field)];
38+
static_assert(sizeof(buf) == 8, "Error: sizeof(HEADER.VERSION) != 8");
39+
};
40+
41+
union OtaHeader
42+
{
43+
struct __attribute__((packed))
44+
{
45+
uint32_t len;
46+
uint32_t crc32;
47+
uint32_t magic_number;
48+
HeaderVersion hdr_version;
49+
} header;
50+
uint8_t buf[sizeof(header)];
51+
static_assert(sizeof(buf) == 20, "Error: sizeof(HEADER) != 20");
52+
};
53+
54+
uint32_t crc_update(uint32_t crc, const void * data, size_t data_len);
55+
56+
#endif /* ESP_OTA_UTILITY_H_ */

‎src/tls/amazon_root_ca.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/* Certificates from https://www.amazontrust.com/repository/ */
2+
3+
#ifndef ESP_OTA_AMAZON_ROOT_CA_H_
4+
#define ESP_OTA_AMAZON_ROOT_CA_H_
5+
6+
const char* amazon_root_ca = \
7+
/* Amazon Root CA 1 */
8+
"-----BEGIN CERTIFICATE-----\n" \
9+
"MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD\n" \
10+
"VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1\n" \
11+
"MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv\n" \
12+
"bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" \
13+
"ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH\n" \
14+
"FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ\n" \
15+
"gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t\n" \
16+
"dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce\n" \
17+
"VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB\n" \
18+
"/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3\n" \
19+
"DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM\n" \
20+
"CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy\n" \
21+
"8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa\n" \
22+
"2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2\n" \
23+
"xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5\n" \
24+
"-----END CERTIFICATE-----\n" \
25+
/* Amazon Root CA 2 */
26+
"-----BEGIN CERTIFICATE-----\n" \
27+
"MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD\n" \
28+
"VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1\n" \
29+
"MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv\n" \
30+
"bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC\n" \
31+
"ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4\n" \
32+
"kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp\n" \
33+
"N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9\n" \
34+
"AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd\n" \
35+
"fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx\n" \
36+
"kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS\n" \
37+
"btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0\n" \
38+
"Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN\n" \
39+
"c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+\n" \
40+
"3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw\n" \
41+
"DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA\n" \
42+
"A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY\n" \
43+
"+gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE\n" \
44+
"YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW\n" \
45+
"xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ\n" \
46+
"gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW\n" \
47+
"aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV\n" \
48+
"Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3\n" \
49+
"KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi\n" \
50+
"JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=\n" \
51+
"-----END CERTIFICATE-----\n" \
52+
/* Amazon Root CA 3 */
53+
"-----BEGIN CERTIFICATE-----\n" \
54+
"MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG\n" \
55+
"EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy\n" \
56+
"NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ\n" \
57+
"MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB\n" \
58+
"f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr\n" \
59+
"Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43\n" \
60+
"rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc\n" \
61+
"eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==\n" \
62+
"-----END CERTIFICATE-----\n" \
63+
/* Amazon Root CA 4 */
64+
"-----BEGIN CERTIFICATE-----\n" \
65+
"MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG\n" \
66+
"EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy\n" \
67+
"NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ\n" \
68+
"MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN\n" \
69+
"/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri\n" \
70+
"83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\n" \
71+
"HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA\n" \
72+
"MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1\n" \
73+
"AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==\n" \
74+
"-----END CERTIFICATE-----\n";
75+
76+
#endif /* ESP_OTA_AMAZON_ROOT_CA_H_ */

0 commit comments

Comments
 (0)
Please sign in to comment.