mirror of
https://github.com/Fishwaldo/esp_ghota.git
synced 2025-03-15 19:31:37 +00:00
Documentation
This commit is contained in:
parent
2490177c4d
commit
24005abcce
13 changed files with 2945 additions and 12 deletions
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
|
@ -19,7 +19,7 @@ jobs:
|
|||
with:
|
||||
submodules: 'recursive'
|
||||
- name: esp-idf build
|
||||
uses: Fishwaldo/esp-idf-ci-action@v1.1
|
||||
uses: Fishwaldo/esp-idf-ci-action@v1.2
|
||||
with:
|
||||
esp_idf_version: v4.4.3
|
||||
target: ${{ matrix.targets }}
|
||||
|
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -55,3 +55,7 @@ dkms.conf
|
|||
build/
|
||||
dependencies.lock
|
||||
sdkconfig
|
||||
docs/build
|
||||
docs/latex
|
||||
*~
|
||||
|
||||
|
|
10
README.md
10
README.md
|
@ -118,14 +118,16 @@ jobs:
|
|||
with:
|
||||
submodules: 'recursive'
|
||||
- name: esp-idf build
|
||||
uses: espressif/esp-idf-ci-action@v1
|
||||
uses: Fishwaldo/esp-idf-ci-action@v1.1
|
||||
with:
|
||||
esp_idf_version: v4.4
|
||||
esp_idf_version: v4.4.3
|
||||
target: ${{ matrix.targets }}
|
||||
path: 'examples/esp_ghota_example'
|
||||
- name: Rename artifact
|
||||
run: |
|
||||
cp build/GithubOTA.bin GithubOTA-${{ matrix.targets }}.bin
|
||||
cp build/storage.bin storage-${{ matrix.targets }}.bin
|
||||
ls -lah
|
||||
cp examples/esp_ghota_example/build/esp_ghota_example.bin esp_ghota_example-${{ matrix.targets }}.bin
|
||||
cp examples/esp_ghota_example/build/storage.bin storage-${{ matrix.targets }}.bin
|
||||
- name: Archive Firmware Files
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
|
|
2579
docs/Doxyfile
Normal file
2579
docs/Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
20
docs/Makefile
Normal file
20
docs/Makefile
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
151
docs/README.md
Normal file
151
docs/README.md
Normal file
|
@ -0,0 +1,151 @@
|
|||
# GITHUB OTA for ESP32 devices
|
||||
|
||||
Automate your OTA and CI/CD pipeline with Github Actions to update your ESP32 devices in the field direct from github releases
|
||||
|
||||
## Features
|
||||
* Uses the esp_htps_ota library under the hood to update firmware images
|
||||
* Can also update spiffs/littlefs/fatfs partitions
|
||||
* Uses SemVer to compare versions and only update if a newer version is available
|
||||
* Plays nicely with App rollback and anti-rollback features of the esp-idf bootloader
|
||||
* Download firmware and partitiion images from the github release page directly
|
||||
* Supports multiple devices with different firmware images
|
||||
* Includes a sample Github Actions that builds and releases images when a new tag is pushed
|
||||
* Updates can be triggered manually, or via a interval timer
|
||||
* Uses a streaming JSON parser for to reduce memory usage (Github API responses can be huge)
|
||||
* Supports Private Repositories (Github API token required*)
|
||||
* Supports Github Enterprise
|
||||
* Supports Github Personal Access Tokens to overcome Github API Ratelimits
|
||||
* Sends progress of Updates via the esp_event_loop
|
||||
|
||||
Note:
|
||||
You should be careful with your GitHub PAT and putting it in the source code. I would suggest that you store the PAT in NVS, and the user enters it when running, as otherwise the PAT would be easily extractable from your firmware images.
|
||||
|
||||
## Usage
|
||||
|
||||
via the Espressif Component Registry:
|
||||
|
||||
```bash
|
||||
idf.py add-dependency Fishwaldo/ghota^1.0.0
|
||||
```
|
||||
|
||||
## Example
|
||||
After Initilizing Network Access, Start a timer to periodically check for new releases:
|
||||
|
||||
```c
|
||||
ghota_config_t ghconfig = {
|
||||
.filenamematch = "GithubOTA-esp32.bin", // Glob Pattern to match against the Firmware file
|
||||
.storagenamematch = "storage-esp32.bin", // Glob Pattern to match against the storage firmware file
|
||||
.storagepartitionname = "storage", // Update the storage partition
|
||||
.updateInterval = 60, // Check for updates every 60 minuites
|
||||
};
|
||||
ghota_client_handle_t *ghota_client = ghota_init(&ghconfig);
|
||||
if (ghota_client == NULL) {
|
||||
ESP_LOGE(TAG, "ghota_client_init failed");
|
||||
return;
|
||||
}
|
||||
esp_event_handler_register(GHOTA_EVENTS, ESP_EVENT_ANY_ID, &ghota_event_callback, ghota_client); // Register a handler to get updates on progress
|
||||
ESP_ERROR_CHECK(ghota_start_update_timer(ghota_client)); // Start the timer to check for updates
|
||||
```
|
||||
|
||||
Manually Checking for updates:
|
||||
|
||||
```c
|
||||
ghota_config_t ghconfig = {
|
||||
.filenamematch = "GithubOTA-esp32.bin",
|
||||
.storagenamematch = "storage-esp32.bin",
|
||||
.storagepartitionname = "storage",
|
||||
.updateInterval = 60,
|
||||
};
|
||||
ghota_client_handle_t *ghota_client = ghota_init(&ghconfig);
|
||||
if (ghota_client == NULL) {
|
||||
ESP_LOGE(TAG, "ghota_client_init failed");
|
||||
return;
|
||||
}
|
||||
esp_event_handler_register(GHOTA_EVENTS, ESP_EVENT_ANY_ID, &ghota_event_callback, ghota_client);
|
||||
ESP_ERROR_CHECK(ghota_check(ghota_client));
|
||||
|
||||
semver_t *cur = ghota_get_current_version(ghota_client);
|
||||
if (cur) {
|
||||
ESP_LOGI(TAG, "Current version: %d.%d.%d", cur->major, cur->minor, cur->patch);
|
||||
semver_free(cur);
|
||||
}
|
||||
|
||||
semver_t *new = ghota_get_latest_version(ghota_client);
|
||||
if (new) {
|
||||
ESP_LOGI(TAG, "New version: %d.%d.%d", new->major, new->minor, new->patch);
|
||||
semver_free(new);
|
||||
}
|
||||
ESP_ERROR_CHECK(ghota_update(ghota_client));
|
||||
ESP_ERROR_CHECK(ghota_free(ghota_client));
|
||||
```
|
||||
|
||||
## Configuration
|
||||
The following configuration options are available:
|
||||
|
||||
* config.filenamematch <- Glob pattern to match against the firmware file from the Github Releases page.
|
||||
* config.storagenamematch <- Glob pattern to match against the storage file from the Github Releases page.
|
||||
* config.storagepartitionname <- Name of the storage partition to update (as defined in partitions.csv)
|
||||
* config.hostname <- Hostname of the Github API (default: api.github.com)
|
||||
* config.orgname <- Name of the Github User or Organization
|
||||
* config.reponame <- Name of the Github Repository
|
||||
* config.updateInterval <- Interval in minutes to check for updates
|
||||
|
||||
## Github Actions
|
||||
The Github Actions included in this repository can be used to build and release firmware images to Github Releases.
|
||||
This is a good way to automate your CI/CD pipeline, and update your devices in the field.
|
||||
In this example, we build two variants of the Firmware - on for a ESP32 and one for a ESP32-S3 device
|
||||
Using the filenamematch and storagenamematch config options, we can match against the correct firmware image for the device.
|
||||
|
||||
```yaml
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
name: Build
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
targets: [esp32, esp32s3]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: esp-idf build
|
||||
uses: espressif/esp-idf-ci-action@v1
|
||||
with:
|
||||
esp_idf_version: v4.4
|
||||
target: ${{ matrix.targets }}
|
||||
- name: Rename artifact
|
||||
run: |
|
||||
cp build/GithubOTA.bin GithubOTA-${{ matrix.targets }}.bin
|
||||
cp build/storage.bin storage-${{ matrix.targets }}.bin
|
||||
- name: Archive Firmware Files
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ matrix.targets }}-firmware
|
||||
path: "*-${{ matrix.targets }}.bin"
|
||||
|
||||
release:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download Firmware Files
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
path: release
|
||||
- name: Release Firmware
|
||||
uses: ncipollo/release-action@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
artifacts: release/*/*.bin
|
||||
generateReleaseNotes: true
|
||||
allowUpdates: true
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
```
|
11
docs/api/ghota.rst
Normal file
11
docs/api/ghota.rst
Normal file
|
@ -0,0 +1,11 @@
|
|||
.. _esp_ghota:
|
||||
|
||||
Main API
|
||||
========
|
||||
|
||||
esp_ghota.h contains the main API for the library.
|
||||
|
||||
|
||||
API Details
|
||||
-----------
|
||||
.. doxygenfile:: esp_ghota.h
|
12
docs/api/semver.rst
Normal file
12
docs/api/semver.rst
Normal file
|
@ -0,0 +1,12 @@
|
|||
.. _semver:
|
||||
|
||||
semver.h
|
||||
===========
|
||||
|
||||
The Semver support comes from https://github.com/h2non/semver.c
|
||||
|
||||
You can use this to compare released and installed versions of the firmware.
|
||||
|
||||
consult the above github repo for more information on using the functions defined in this header.
|
||||
|
||||
.. doxygenfile:: semver.h
|
8
docs/changelog.rst
Normal file
8
docs/changelog.rst
Normal file
|
@ -0,0 +1,8 @@
|
|||
Recent Changes
|
||||
==============
|
||||
|
||||
Prior to Version 1.0.0, the following changes were made:
|
||||
|
||||
.. git_changelog::
|
||||
:revisions: 500
|
||||
|
116
docs/conf.py
Normal file
116
docs/conf.py
Normal file
|
@ -0,0 +1,116 @@
|
|||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# For the full list of built-in configuration values, see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
|
||||
project = 'Github OTA'
|
||||
copyright = '2022, Justin Hammond'
|
||||
author = 'Justin Hammond'
|
||||
|
||||
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = re.sub('^v', '', os.popen('git describe').read().strip())
|
||||
# The short X.Y version.
|
||||
version = release
|
||||
|
||||
version = "0.0.1"
|
||||
release = "0.0.1"
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.doctest',
|
||||
'sphinx.ext.mathjax',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx.ext.imgmath',
|
||||
'sphinx.ext.todo',
|
||||
'breathe',
|
||||
'sphinx_git',
|
||||
'myst_parser',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
# templates_path = ['_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = 'en'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = None
|
||||
|
||||
|
||||
templates_path = ['_templates']
|
||||
exclude_patterns = []
|
||||
|
||||
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
import sphinx_rtd_theme
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
# html_theme = 'alabaster'
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
# html_static_path = ['_static']
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
#
|
||||
# The default sidebars (for documents that don't match any pattern) are
|
||||
# defined by theme itself. Builtin themes are using these templates by
|
||||
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
|
||||
# 'searchbox.html']``.
|
||||
#
|
||||
# html_sidebars = {}
|
||||
|
||||
|
||||
import subprocess
|
||||
subprocess.call('make clean', shell=True)
|
||||
subprocess.call('doxygen', shell=True)
|
||||
|
||||
breathe_projects = { "Github OTA": "build/xml/" }
|
||||
breathe_default_project = "Github OTA"
|
27
docs/index.rst
Normal file
27
docs/index.rst
Normal file
|
@ -0,0 +1,27 @@
|
|||
.. Github OTA documentation master file, created by
|
||||
sphinx-quickstart on Sun Nov 27 23:58:20 2022.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to Github OTA's documentation!
|
||||
======================================
|
||||
|
||||
This documentation is work in progress. Please refer to the [examples](https://github.com/Fishwaldo/esp_ghota/tree/master/examples) directory for working examples
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
../README.md
|
||||
|
||||
api/ghota.rst
|
||||
api/semver.rst
|
||||
|
||||
changelog.rst
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
3
docs/requirements.txt
Normal file
3
docs/requirements.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
breathe
|
||||
sphinx-git
|
||||
myst-parser
|
|
@ -35,13 +35,13 @@ typedef enum
|
|||
* @brief Github OTA Configuration
|
||||
*/
|
||||
typedef struct ghota_config_t {
|
||||
char filenamematch[CONFIG_MAX_FILENAME_LEN]; /**< Filename to match against on Github indicating this is a firmware file */
|
||||
char storagenamematch[CONFIG_MAX_FILENAME_LEN]; /**< Filename to match against on Github indicating this is a storage file */
|
||||
char storagepartitionname[17]; /**< Name of the storage partition to update */
|
||||
char *hostname; /**< Hostname of the Github server. Defaults to api.github.com*/
|
||||
char *orgname; /**< Name of the Github organization */
|
||||
char *reponame; /**< Name of the Github repository */
|
||||
uint32_t updateInterval; /**< Interval in Minutes to check for updates if using the ghota_start_update_timer function */
|
||||
char filenamematch[CONFIG_MAX_FILENAME_LEN]; /*!< Filename to match against on Github indicating this is a firmware file */
|
||||
char storagenamematch[CONFIG_MAX_FILENAME_LEN]; /*!< Filename to match against on Github indicating this is a storage file */
|
||||
char storagepartitionname[17]; /*!< Name of the storage partition to update */
|
||||
char *hostname; /*!< Hostname of the Github server. Defaults to api.github.com*/
|
||||
char *orgname; /*!< Name of the Github organization */
|
||||
char *reponame; /*!< Name of the Github repository */
|
||||
uint32_t updateInterval; /*!< Interval in Minutes to check for updates if using the ghota_start_update_timer function */
|
||||
} ghota_config_t;
|
||||
|
||||
typedef struct ghota_client_handle_t ghota_client_handle_t;
|
||||
|
|
Loading…
Add table
Reference in a new issue