From f6a2ae7dba7eafe89495e26fb603849d30e93be6 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Thu, 8 Aug 2024 09:26:42 +0200 Subject: [PATCH 01/74] moves `arduino-lint`, `arduino`, `cpp`, and `doxygen` Make targets to `workloads/tooling` --- Makefile | 9 ++-- arduino-lint.mk | 16 ------ arduino.mk | 135 ------------------------------------------------ cpp.mk | 38 -------------- doxygen.mk | 41 --------------- 5 files changed, 5 insertions(+), 234 deletions(-) delete mode 100644 arduino-lint.mk delete mode 100644 arduino.mk delete mode 100644 cpp.mk delete mode 100644 doxygen.mk diff --git a/Makefile b/Makefile index 6541de1..d5366d8 100644 --- a/Makefile +++ b/Makefile @@ -5,10 +5,11 @@ MAKEFILE_TITLE = 🧭 PATHFINDER include ../tooling/make/configs/shared.mk include ../tooling/make/functions/shared.mk -include ./arduino-lint.mk -include ./cpp.mk +include ../tooling/make/targets/arduino-lint.mk +include ../tooling/make/targets/cpp.mk include ../tooling/make/targets/yamllint.mk -include ./arduino.mk -include ./doxygen.mk +include ../tooling/make/targets/arduino.mk +include ../tooling/make/targets/doxygen.mk include ../tooling/make/targets/shared.mk +include ../tooling/make/targets/vale.mk include ./config.mk diff --git a/arduino-lint.mk b/arduino-lint.mk deleted file mode 100644 index b8affca..0000000 --- a/arduino-lint.mk +++ /dev/null @@ -1,16 +0,0 @@ -# arduino-lint-specific Make Targets - -# TODO: integrate with `workloads/tooling` - -BINARY_ARDUINO_LINT ?= arduino-lint - -FORMAT_ARDUINO_LINT ?= text - - -.SILENT .PHONY: lint-arduino -lint-arduino: # lint Arduino code using arduino-lint [Usage: `make lint-arduino`] - $(BINARY_ARDUINO_LINT) \ - --compliance strict \ - --format $(FORMAT_ARDUINO_LINT) \ - --project-type all \ - ; diff --git a/arduino.mk b/arduino.mk deleted file mode 100644 index df77ed6..0000000 --- a/arduino.mk +++ /dev/null @@ -1,135 +0,0 @@ -# Arduino-specific Make Targets - -# TODO: integrate with `workloads/tooling` - -BINARY_ARDUINO_CLI ?= arduino-cli - - -.SILENT .PHONY: attach -attach: # attach Arduino Board using arduino-cli [Usage: `make attach`] - $(call print_reference,"$(ARDUINO_SKETCH_CONFIG)") - - echo - - # see https://arduino.github.io/arduino-cli/1.0/commands/arduino-cli_board_attach/ - $(BINARY_ARDUINO_CLI) \ - board \ - attach \ - --config-file "$(ARDUINO_SKETCH_CONFIG)" \ - ; - -.SILENT .PHONY: clean -clean: # clean Arduino cache using arduino-cli [Usage: `make clean`] - # see https://arduino.github.io/arduino-cli/1.0/commands/arduino-cli_cache_clean/ - $(BINARY_ARDUINO_CLI) \ - cache \ - clean \ - --config-file "$(ARDUINO_SKETCH_CONFIG)" \ - ; - - -.SILENT .PHONY: compile -compile: # compile Arduino Sketch using arduino-cli [Usage: `make compile`] - $(call print_reference,"$(ARDUINO_SKETCH_FILE)") - - # see https://arduino.github.io/arduino-cli/1.0/commands/arduino-cli_compile/ - # and https://arduino.github.io/arduino-cli/1.0/sketch-build-process/ - $(BINARY_ARDUINO_CLI) \ - compile \ - --clean \ - --config-file "$(ARDUINO_SKETCH_CONFIG)" \ - --discovery-timeout "$(ARDUINO_CLI_COMPILE_DISCOVERY_TIMEOUT)" \ - --jobs "$(ARDUINO_CLI_COMPILE_JOBS)" \ - --output-dir "$(ARDUINO_CLI_COMPILE_OUTPUT_DIRECTORY)" \ - --profile "$(ARDUINO_SKETCH_PROFILE)" \ - --protocol "$(ARDUINO_CLI_COMPILE_PROTOCOL)" \ - --quiet \ - --verify \ - --warnings "$(ARDUINO_CLI_COMPILE_WARNINGS)" \ - $(ARDUINO_SKETCH_FILE) \ - ; - - -.SILENT .PHONY: upload -upload: # upload binary artifact using arduino-cli [Usage: `make upload`] - $(call print_reference,"$(ARDUINO_CLI_COMPILE_OUTPUT_DIRECTORY)") - - echo - - # see https://arduino.github.io/arduino-cli/1.0/commands/arduino-cli_compile/ - $(BINARY_ARDUINO_CLI) \ - upload \ - --config-fil "$(ARDUINO_SKETCH_CONFIG)" \ - --discovery-timeout "$(ARDUINO_CLI_COMPILE_DISCOVERY_TIMEOUT)" \ - --input-dir "$(ARDUINO_CLI_COMPILE_OUTPUT_DIRECTORY)" \ - --profile "$(ARDUINO_SKETCH_PROFILE)" \ - --protocol "$(ARDUINO_CLI_COMPILE_PROTOCOL)" \ - --verify - ; - - -.SILENT .PHONY: monitor -monitor: # monitor binary output using arduino-cli [Usage: `make monitor`] - $(call print_arg,"baudrate",$(ARDUINO_CLI_MONITOR_BAUDRATE)) - - echo - - # see https://arduino.github.io/arduino-cli/1.0/commands/arduino-cli_monitor/ - $(BINARY_ARDUINO_CLI) \ - monitor \ - --config "$(ARDUINO_CLI_MONITOR_BAUDRATE)" \ - --config-file "$(ARDUINO_SKETCH_CONFIG)" \ - --discovery-timeout "$(ARDUINO_CLI_COMPILE_DISCOVERY_TIMEOUT)" \ - --timestamp \ - ; - - -.SILENT .PHONY: install-cores -install-cores: # install Arduino Board Core using arduino-cli [Usage: `make install-cores`] - $(call print_reference,"$(ARDUINO_CORES)") - - # see https://arduino.github.io/arduino-cli/1.0/commands/arduino-cli_core_install/ - $(BINARY_ARDUINO_CLI) \ - core \ - install \ - --config-file "$(ARDUINO_SKETCH_CONFIG)" \ - $(ARDUINO_CORES) \ - ; - - -.SILENT .PHONY: install-libs -install-libs: # install Arduino libraries using arduino-cli [Usage: `make install-libs`] - echo "⚠️ Installing and updating upstream libraries" - - # see https://arduino.github.io/arduino-cli/1.0/commands/arduino-cli_lib_install/ - $(BINARY_ARDUINO_CLI) \ - lib \ - install \ - --config-file "$(ARDUINO_SKETCH_CONFIG)" \ - $(ARDUINO_LIBRARIES_UPSTREAM) \ - ; - -# echo -# echo "⚠️ Installing and updating unsafe libraries" -# -# # see https://arduino.github.io/arduino-cli/1.0/commands/arduino-cli_lib_install/ -# $(foreach ITEM,$(ARDUINO_LIBRARIES_UNSAFE), \ -# $(BINARY_ARDUINO_CLI) \ -# lib \ -# --config-file "$(ARDUINO_SKETCH_CONFIG)" \ -# install \ -# --git-url $(ITEM) \ - ) - -.SILENT .PHONY: list-libs -list-libs: # list Arduino libraries using arduino-cli [Usage: `make list-libs`] - $(call print_reference,"$(ARDUINO_SKETCH_CONFIG)") - - # see https://arduino.github.io/arduino-cli/1.0/commands/arduino-cli_lib_list/ - $(BINARY_ARDUINO_CLI) \ - lib \ - list \ - --all \ - --config-file "$(ARDUINO_SKETCH_CONFIG)" \ - ; - diff --git a/cpp.mk b/cpp.mk deleted file mode 100644 index 4e4e53b..0000000 --- a/cpp.mk +++ /dev/null @@ -1,38 +0,0 @@ -# Cpp-specific Make Targets - -# TODO: integrate with `workloads/tooling` - -BINARY_CPPLINT ?= cpplint -BINARY_CLANG_FORMAT ?= clang-format - -TARGET_DIR_SRC = ./src -TARGET_FILES_INO = $(wildcard *.ino) -TARGET_FILES_SRC = $(wildcard $(TARGET_DIR_SRC)/*.cpp $(TARGET_DIR_SRC)/*.h) - -# Combine lists -TARGET_FILES = $(TARGET_FILES_INO) $(TARGET_FILES_SRC) - - -.SILENT .PHONY: lint-cpp -lint-cpp: # lint C++ code using cpplint and clang-format [Usage: `make lint-cpp`] - $(call print_reference,"$(TARGET_FILES_INO)") - $(BINARY_CPPLINT) \ - $(TARGET_FILES_INO) \ - ; - - echo - - $(call print_reference,"$(TARGET_DIR_SRC)") - $(BINARY_CPPLINT) \ - $(TARGET_FILES_SRC) \ - ; - - echo - - $(call print_reference,$(BINARY_CLANG_FORMAT)) - $(BINARY_CLANG_FORMAT) \ - -i \ - $(TARGET_FILES) \ - ; - - echo \ No newline at end of file diff --git a/doxygen.mk b/doxygen.mk deleted file mode 100644 index 619be96..0000000 --- a/doxygen.mk +++ /dev/null @@ -1,41 +0,0 @@ -# Doxygen-specific Make Targets - -# TODO: integrate with `workloads/tooling` - -BINARY_DOXYGEN ?= doxygen -BINARY_GIT ?= git - -CONFIG_DOXYGEN ?= Doxyfile -FORMAT_DOXYGEN ?= html - -# see https://jothepro.github.io/doxygen-awesome-css/ -DOXYGEN_THEME_URL ?= "https://github.com/jothepro/doxygen-awesome-css.git" -DOXYGEN_THEME_PATH ?= ".doxygen/theme" - - -.SILENT .PHONY: docs -docs: # create docs using doxygen [Usage: `make docs`] - $(BINARY_DOXYGEN) \ - #-w $(FORMAT_DOXYGEN) \ - $(CONFIG_DOXYGEN) \ - ; - - -docs-get-theme: # retrieve Doxygen theme using git [Usage: `make docs-get-theme`] - if [ ! -d "$(DOXYGEN_THEME_PATH)" ]; then \ - echo "$(DOXYGEN_THEME_PATH) does not exist, cloning repository." \ - ; \ - $(BINARY_GIT) \ - clone \ - $(DOXYGEN_THEME_URL) \ - $(DOXYGEN_THEME_PATH) \ - ; \ - else \ - echo "$(DOXYGEN_THEME_PATH) already exists, pulling latest changes." \ - ; \ - cd $(DOXYGEN_THEME_PATH) \ - ; \ - $(BINARY_GIT) \ - pull \ - ; \ - fi \ No newline at end of file From a73478638fedf87fd9c8bf1217355f2411a1e86f Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Thu, 8 Aug 2024 09:27:00 +0200 Subject: [PATCH 02/74] linting --- .yaml-lint.yml | 1 + sketch.yml | 48 +++++++++++++++++++++++++++++------------------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/.yaml-lint.yml b/.yaml-lint.yml index 34657ff..e321737 100644 --- a/.yaml-lint.yml +++ b/.yaml-lint.yml @@ -4,6 +4,7 @@ extends: default ignore: - ".arduino/" + - ".doxygen/" yaml-files: diff --git a/sketch.yml b/sketch.yml index 3ba4d7e..865cf99 100644 --- a/sketch.yml +++ b/sketch.yml @@ -27,51 +27,61 @@ profiles: # UPSTREAM LIBRARIES # ################################################################################ - - # see https://github.com/adafruit/Adafruit_BusIO + - + # see https://github.com/adafruit/Adafruit_BusIO Adafruit BusIO (1.16.1) - - # see https://github.com/adafruit/Adafruit-GFX-Library + - + # see https://github.com/adafruit/Adafruit-GFX-Library Adafruit GFX Library (1.11.10) - - # see https://github.com/adafruit/Adafruit_ICM20X + - + # see https://github.com/adafruit/Adafruit_ICM20X Adafruit ICM20X (2.0.7) - - # see https://github.com/adafruit/Adafruit_SSD1306 + - + # see https://github.com/adafruit/Adafruit_SSD1306 Adafruit SSD1306 (2.5.11) - - # see https://github.com/adafruit/Adafruit_Sensor + - + # see https://github.com/adafruit/Adafruit_Sensor Adafruit Unified Sensor (1.1.14) - - # see https://github.com/bblanchon/ArduinoJson + - + # see https://github.com/bblanchon/ArduinoJson ArduinoJson (7.1.0) - - # see https://github.com/ricaun/ArduinoUniqueID + - + # see https://github.com/ricaun/ArduinoUniqueID ArduinoUniqueID (1.3.0) - - # see https://github.com/madhephaestus/ESP32Encoder + - + # see https://github.com/madhephaestus/ESP32Encoder ESP32Encoder (0.11.6) - - # see https://github.com/wollewald/ICM20948_WE + - + # see https://github.com/wollewald/ICM20948_WE ICM20948_WE (1.1.8) - - # see https://github.com/wollewald/INA219_WE + - + # see https://github.com/wollewald/INA219_WE INA219_WE (1.3.8) - - # see https://github.com/lorol/LITTLEFS + - + # see https://github.com/lorol/LITTLEFS LittleFS_esp32 (1.0.6) - - # see https://github.com/jacksonliam/PID_v2 + - + # see https://github.com/jacksonliam/PID_v2 PID_v2 (2.0.1) - - # see https://github.com/denyssene/SimpleKalmanFilter + - + # see https://github.com/denyssene/SimpleKalmanFilter SimpleKalmanFilter (0.1) - ################################################################################ - # UNSAFE LIBRARIES # - ################################################################################ - - #- # see https://github.com/workloads/scservo.git - # SCServo (1.0.1) + - + # see https://github.com/workloads/scservo.git + SCServo (1.0.1) # see https://arduino.github.io/arduino-cli/1.0/platform-specification/ From e28d7c27d1e233c810888ed39ad4bb51e5d98871 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Thu, 8 Aug 2024 15:06:47 +0200 Subject: [PATCH 03/74] bumps version from `0.9.5` to `0.10.0` --- pathfinder.ino | 2 +- sketch.yml | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pathfinder.ino b/pathfinder.ino index 5afab03..d656a15 100644 --- a/pathfinder.ino +++ b/pathfinder.ino @@ -3,7 +3,7 @@ * @file pathfinder.ino * @brief ESP32-based mobile edge computing platform * @url https://go.workloads.io/pathfinder - * @version 0.9.5 + * @version 0.10.0 * */ diff --git a/sketch.yml b/sketch.yml index 865cf99..c87a9be 100644 --- a/sketch.yml +++ b/sketch.yml @@ -75,14 +75,13 @@ profiles: # see https://github.com/jacksonliam/PID_v2 PID_v2 (2.0.1) - - - # see https://github.com/denyssene/SimpleKalmanFilter - SimpleKalmanFilter (0.1) - - # see https://github.com/workloads/scservo.git - SCServo (1.0.1) + #SCServo (1.0.1) + - + # see https://github.com/denyssene/SimpleKalmanFilter + SimpleKalmanFilter (0.1) # see https://arduino.github.io/arduino-cli/1.0/platform-specification/ platforms: From c0e7a500112ee6f8e1b9cc35cd9f971080f67713 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Thu, 8 Aug 2024 18:27:30 +0200 Subject: [PATCH 04/74] updates link to correct datasheet --- README.md | 4 +++- config.mk | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 371a260..1d1abcf 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,9 @@ This repository does not include any datasheets directly. For an overview of the WAVE ROVER hardware, see [waveshare.com](https://www.waveshare.com/wiki/WAVE_ROVER#Resource). -For an overview of the ESP32 hardware, see [espressif.com](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf). +For an overview of the ESP32 hardware, see [espressif.com](https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32e_esp32-wroom-32ue_datasheet_en.pdf). + +The _Mobility Platform_ uses the `ESP32-WROOM-32UE-N4` module. ### Delays diff --git a/config.mk b/config.mk index 01bb964..21b5172 100644 --- a/config.mk +++ b/config.mk @@ -16,6 +16,7 @@ ARDUINO_CLI_COMPILE_PROTOCOL = "serial" ARDUINO_CLI_COMPILE_WARNINGS = "default" # baudrate for the serial monitor +# ⚠️ If this value is updated, it MUST be updated project-wide ARDUINO_CLI_MONITOR_BAUDRATE ?= "115200" # board core and version to be used for compiling the sketch From 422e96b158cb05e296b345fdb22f732b9da6e8d7 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Thu, 8 Aug 2024 23:22:42 +0200 Subject: [PATCH 05/74] adds datasheet for OLED display --- README.md | 8 +++----- config.mk | 5 +---- pathfinder.ino | 4 ++-- sketch.yml | 1 + 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 1d1abcf..07b5ab4 100644 --- a/README.md +++ b/README.md @@ -115,11 +115,9 @@ _selfcheck lint Makefile `make _selfchec This repository does not include any datasheets directly. -For an overview of the WAVE ROVER hardware, see [waveshare.com](https://www.waveshare.com/wiki/WAVE_ROVER#Resource). - -For an overview of the ESP32 hardware, see [espressif.com](https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32e_esp32-wroom-32ue_datasheet_en.pdf). - -The _Mobility Platform_ uses the `ESP32-WROOM-32UE-N4` module. +* for the Waveshare WAVE ROVER`, see [waveshare.com](https://www.waveshare.com/wiki/WAVE_ROVER#Resource) +* for the Waveshare OLED module, see [waveshare.com](https://www.waveshare.com/wiki/0.91inch_OLED_Module) +* for the ESP32 `WROOM-32UE-N4` module, see [espressif.com](https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32e_esp32-wroom-32ue_datasheet_en.pdf) ### Delays diff --git a/config.mk b/config.mk index 21b5172..7392dd9 100644 --- a/config.mk +++ b/config.mk @@ -1,7 +1,7 @@ # project-specific configuration for Pathfinder # timeout for the board discovery process -ARDUINO_CLI_COMPILE_DISCOVERY_TIMEOUT = "1s" +ARDUINO_CLI_COMPILE_DISCOVERY_TIMEOUT = "10s" # number of parallel jobs to use for compiling the sketch ARDUINO_CLI_COMPILE_JOBS ?= "0" @@ -9,9 +9,6 @@ ARDUINO_CLI_COMPILE_JOBS ?= "0" # output directory for compiled artifacts ARDUINO_CLI_COMPILE_OUTPUT_DIRECTORY = "./build" -# protocol to use for compiling the sketch -ARDUINO_CLI_COMPILE_PROTOCOL = "serial" - # warning level for the compile process ARDUINO_CLI_COMPILE_WARNINGS = "default" diff --git a/pathfinder.ino b/pathfinder.ino index d656a15..b97423e 100644 --- a/pathfinder.ino +++ b/pathfinder.ino @@ -8,8 +8,8 @@ */ #ifndef CORE_DEBUG_LEVEL -// Levels `INFO`, `DEBUG`, and `VERBOSE` may result in a performance decrease -#define CORE_DEBUG_LEVEL LOG_INFO +// ⚠️ Levels `LOG_INFO`, `LOG_DEBUG`, and `LOG_VERBOSE` may result in a performance decrease +#define CORE_DEBUG_LEVEL LOG_ERROR #endif // TaskHandle_t Pid_ctrl; diff --git a/sketch.yml b/sketch.yml index c87a9be..a61169c 100644 --- a/sketch.yml +++ b/sketch.yml @@ -9,6 +9,7 @@ default_fqbn: "esp32:esp32:esp32" default_port: "/dev/cu.usbserial-1210" default_profile: default default_programmer: esptool +default_protocol: serial profiles: # see https://arduino.github.io/arduino-cli/1.0/sketch-project-file/#build-profiles From 14c6fc8c783f7c4bbbf6121370d83a1a5bf02701 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Thu, 8 Aug 2024 23:48:11 +0200 Subject: [PATCH 06/74] linting --- config.mk | 2 +- data/devConfig.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 data/devConfig.json diff --git a/config.mk b/config.mk index 7392dd9..4efaaef 100644 --- a/config.mk +++ b/config.mk @@ -37,7 +37,7 @@ ARDUINO_LIBRARIES_UPSTREAM ?= \ "INA219_WE@1.3.8" \ "LittleFS_esp32@1.0.6" \ "PID_v2@2.0.1" \ - "SCServo@1.0.1" \ + "SCServo@1.0.2" \ "SimpleKalmanFilter@0.1" # list of unsafe / non-upstream Arduino libraries to be installed diff --git a/data/devConfig.json b/data/devConfig.json deleted file mode 100644 index 352146b..0000000 --- a/data/devConfig.json +++ /dev/null @@ -1 +0,0 @@ -{"wifi_mode_on_boot":3,"sta_ssid":"JSBZY-2.4G","sta_password":"waveshare0755","ap_ssid":"RoArm","ap_password":"12345678"} \ No newline at end of file From ee6d8ab242b79e7e3b979c31dbd07dfade77fd3c Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Thu, 8 Aug 2024 23:48:21 +0200 Subject: [PATCH 07/74] linting --- sketch.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sketch.yml b/sketch.yml index a61169c..9d057d3 100644 --- a/sketch.yml +++ b/sketch.yml @@ -73,12 +73,12 @@ profiles: LittleFS_esp32 (1.0.6) - - # see https://github.com/jacksonliam/PID_v2 + # see https://github.com/imax9000/Arduino-PID-Library PID_v2 (2.0.1) - - + - # see https://github.com/workloads/scservo.git - #SCServo (1.0.1) + SCServo (1.0.2) - # see https://github.com/denyssene/SimpleKalmanFilter From f652225dbc03ff4154f1a5ececcc84a6828c2a81 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Fri, 9 Aug 2024 10:11:58 +0200 Subject: [PATCH 08/74] linting --- sketch.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sketch.yml b/sketch.yml index 9d057d3..766fcf4 100644 --- a/sketch.yml +++ b/sketch.yml @@ -9,7 +9,6 @@ default_fqbn: "esp32:esp32:esp32" default_port: "/dev/cu.usbserial-1210" default_profile: default default_programmer: esptool -default_protocol: serial profiles: # see https://arduino.github.io/arduino-cli/1.0/sketch-project-file/#build-profiles @@ -76,7 +75,7 @@ profiles: # see https://github.com/imax9000/Arduino-PID-Library PID_v2 (2.0.1) - - + - # see https://github.com/workloads/scservo.git SCServo (1.0.2) From 6976f19ec0a1e135abcd6e5ae037157abe1d94c9 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 12:51:16 +0200 Subject: [PATCH 09/74] linting --- CMakeLists.txt | 4 ++++ sketch.yml | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f3f009..f125b4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,10 @@ file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.h") # see https://cmake.org/cmake/help/v3.30/command/add_executable.html add_executable(pathfinder pathfinder.ino ${SOURCES}) +# ignore warning about literal suffixes, specifically for `libraries/Insights/src/Insights.cpp:8` +# see https://cmake.org/cmake/help/v3.30/command/add_compile_options.html +add_compile_options(-Wno-literal-suffix) + # explicitly specify language as CXX (C++) # see https://cmake.org/cmake/help/v3.30/command/set_target_properties.html set_target_properties(pathfinder PROPERTIES LINKER_LANGUAGE CXX) diff --git a/sketch.yml b/sketch.yml index 766fcf4..4023fed 100644 --- a/sketch.yml +++ b/sketch.yml @@ -6,7 +6,9 @@ # default flags for Arduino usage # see https://arduino.github.io/arduino-cli/1.0/sketch-project-file/#default-flags-for-arduino-cli-usage default_fqbn: "esp32:esp32:esp32" -default_port: "/dev/cu.usbserial-1210" + +# `default_port` is dynamically set in the `Makefile` + default_profile: default default_programmer: esptool From ae111b81a9ac7a9cfe99cdcf5f4d2a3d2280bfc0 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 20:14:11 +0200 Subject: [PATCH 10/74] code linting tool config updates --- .clang-format | 6 +++++- CPPLINT.cfg | 2 +- config.mk | 3 +-- src/CPPLINT.cfg | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.clang-format b/.clang-format index 3834329..0725f40 100644 --- a/.clang-format +++ b/.clang-format @@ -22,9 +22,13 @@ AlignConsecutiveShortCaseStatements: AlignEscapedNewlines: Left AlignOperands: true -AlignTrailingComments: true + +AlignTrailingComments: + Kind: Always + OverEmptyLines: 2 AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true AllowShortFunctionsOnASingleLine: None AllowShortLoopsOnASingleLine: true diff --git a/CPPLINT.cfg b/CPPLINT.cfg index 4ddd2c9..10287cf 100644 --- a/CPPLINT.cfg +++ b/CPPLINT.cfg @@ -8,6 +8,6 @@ extensions=ino # `legal/copyright` - ignore checks for absence of copyright notices filter=-build/include_order,-legal/copyright -linelength=140 +linelength=120 root=. \ No newline at end of file diff --git a/config.mk b/config.mk index 4efaaef..e5bf649 100644 --- a/config.mk +++ b/config.mk @@ -41,8 +41,7 @@ ARDUINO_LIBRARIES_UPSTREAM ?= \ "SimpleKalmanFilter@0.1" # list of unsafe / non-upstream Arduino libraries to be installed -ARDUINO_LIBRARIES_UNSAFE ?= \ - "https://github.com/workloads/scservo.git" +ARDUINO_LIBRARIES_UNSAFE ?= "" # path to the Arduino sketch configuration file ARDUINO_SKETCH_CONFIG ?= "config.yml" diff --git a/src/CPPLINT.cfg b/src/CPPLINT.cfg index 369787f..5d85dc2 100644 --- a/src/CPPLINT.cfg +++ b/src/CPPLINT.cfg @@ -8,6 +8,6 @@ extensions=cpp,h # `legal/copyright` - ignore checks for absence of copyright notices filter=-build/include_order,-legal/copyright -linelength=140 +linelength=120 root=. \ No newline at end of file From 0807c4fb1e108b76df7c296f31de5c6cd878709c Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 22:21:01 +0200 Subject: [PATCH 11/74] adds Helper functions --- src/Helpers.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/Helpers.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 src/Helpers.cpp create mode 100644 src/Helpers.h diff --git a/src/Helpers.cpp b/src/Helpers.cpp new file mode 100644 index 0000000..85e8271 --- /dev/null +++ b/src/Helpers.cpp @@ -0,0 +1,44 @@ +#include "Helpers.h" + +#include "Log.h" + +bool helperCheckIfStringStartsWithProtocol(const char *input) { + // Check if input starts with "http" (includes "https") + return strncmp(input, "http", 4) == 0; +} + +const char *helperIpAddressToString(IPAddress inputAddr) { + static char output[16]; // Static storage duration to return safely, 15 characters + null terminator + snprintf(output, sizeof(output), "%d.%d.%d.%d", inputAddr[0], inputAddr[1], inputAddr[2], inputAddr[3]); + + logInfo(__func__, "IP Address: %s", output); + + return output; +} + +int helperStringToLogLevel(const char *levelString) { + for (int i = 0; i < logLevelsSize; i++) { + if (strcmp(logLevels[i].name, levelString) == 0) { + logInfo(__func__, "Result: %d", logLevels[i].level); + return logLevels[i].level; + } + } + + // Unknown log level string + return -1; +} + +uint8_t helperPercentageToInteger(int percentage) { + const char *logTag = __func__; + + if (percentage < 0) { + logWarning(logTag, "Percentage outside lower bound, setting to 0"); + percentage = 0; + } else if (percentage > 100) { + logWarning(logTag, "Percentage outside upper bound, setting to 100"); + percentage = 100; + } + + // Calculate integer from percentage + return (uint8_t)((percentage * 255) / 100); +} diff --git a/src/Helpers.h b/src/Helpers.h new file mode 100644 index 0000000..30415bd --- /dev/null +++ b/src/Helpers.h @@ -0,0 +1,49 @@ +#ifndef HELPERS_H_ +#define HELPERS_H_ + +#include +#include + +/** + * @brief Checks if a string starts with a protocol. + * + * This function checks if the input string starts with a protocol, such as `http` or `https`. + * + * @param input The string to check. + * + * @return `true` if the string starts with a protocol, `false` otherwise. + */ +bool helperCheckIfStringStartsWithProtocol(const char *input); + +/** + * @brief Converts IP Address of type IPAddress to a string. + * + * @param inputAddr The IP Address to convert to a string. + * + * @return The string representation of the IP Address. + */ +const char *helperIpAddressToString(IPAddress inputAddr); + +/** + * @brief Converts a string representation of a log level to its corresponding numeric value. + * + * @param levelString The string representation of the log level. + * + * @return The numeric value of the log level, or -1 if the input string is invalid. + */ +int helperStringToLogLevel(const char *levelString); + +/** + * @brief Converts percentage to an integer in the range of 0 to 255. + * + * This function takes a percentage value (0-100) and converts it to + * an integer value (0-255), scaling the percentage to fit the 8-bit + * range. If the input percentage is outside the 0-100 range, it will + * be clamped to ensure the return value stays within bounds. + * + * @param percentage The percentage to convert to an integer. Expected range is 0 to 100. + * @return The integer value of the percentage, scaled to 0-255. + */ +uint8_t helperPercentageToInteger(int percentage); + +#endif // HELPERS_H_ From 9eb440c316c01f2b2b11e0dd4ca3bf0491e733b8 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 22:21:15 +0200 Subject: [PATCH 12/74] adds Device functions --- src/Device.cpp | 143 +++++++++++++++++++++++++++++++++++++++++++++++++ src/Device.h | 35 ++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 src/Device.cpp create mode 100644 src/Device.h diff --git a/src/Device.cpp b/src/Device.cpp new file mode 100644 index 0000000..609f4f7 --- /dev/null +++ b/src/Device.cpp @@ -0,0 +1,143 @@ +#include "Device.h" + +#include "Display.h" + +// TODO(ksatirli) re-enable when upstream warning is fixed +// #include "Insights.h" +#include "Log.h" +#include "WifiClient.h" +#include "WireClient.h" + +//////////////////////////////////////////////////////////////////////////////// +// CONFIGURATION // +//////////////////////////////////////////////////////////////////////////////// + +char applicationCompilationString[32]; + +// TODO(ksatirli) move this to a configuration file +// see https://dashboard.insights.espressif.com/home/manage-auth-keys/ +const char applicationInsightsKey[] = ""; + +// Toggle to sleep HTTP Server +const bool enableHttpServer = false; + +// Toggle to enable ESP Insights +// See https://dashboard.insights.espressif.com/ +const bool enableInsights = false; + +// Toggle to enable configuration changes via serial interface +const bool enableSerialConfiguration = true; +//////////////////////////////////////////////////////////////////////////////// + +char *deviceIdentifier(int length) { + const char *logTag = __func__; + + // Temporary buffer to hold the full UniqueID8 as a hex string + // 8 bytes * 2 characters per byte + 1 for null terminator + char fullIdentifier[17]; + int index = 0; + + for (int i = 0; i < 8; i++) { + if (UniqueID8[i] < 0x10) { + fullIdentifier[index++] = '0'; + } + + // Calculate remaining buffer size + int remainingBufferSize = sizeof(fullIdentifier) - index; + + // Format the current byte in UniqueID8 as lowercase hexadecimal string + snprintf(&fullIdentifier[index], remainingBufferSize, "%02x", UniqueID8[i]); + index += 2; + } + + // Ensure null termination of the full identifier + fullIdentifier[16] = '\0'; + + // Calculate start index to get the last `length` characters + int startIndex = (16 > length) ? (16 - length) : 0; + + // Dynamically allocate memory for the identifier + char *identifier = new char[length + 1]; + + // Copy the last `length` characters from the full identifier + strncpy(identifier, &fullIdentifier[startIndex], length); + + // Ensure null termination + identifier[length] = '\0'; + + return identifier; +} + +bool deviceSetup() { + const char *logTag = __func__; + + // Store compilation time string + snprintf(applicationCompilationString, sizeof(applicationCompilationString), "%s at %s", __DATE__, __TIME__); + + // Print to serial monitor directly as loggers are not yet initialized + char initialLogMessage[64]; + snprintf(initialLogMessage, sizeof(initialLogMessage), "[%s][🏁 START] Initializing device", logTag); + Serial.println(initialLogMessage); + + // Explicitly set the log level + logSetLevel(static_cast(CORE_DEBUG_LEVEL)); + + // Scan for Wi-Fi networks + wifiScanNetworks(); + + // Wi-Fi and other initialization code + if (!wifiDisconnect()) { + logError(logTag, "Failed to disconnect previous Wi-Fi connection"); + + return false; + } + + if (!wifiConnect()) { + logError(logTag, "Failed to establish a Wi-Fi connection"); + + return false; + } + + if (!displayInit()) { + logError(logTag, "Failed to initialize Display"); + + return false; + } + + if (!wireInit()) { + logError(logTag, "Failed to initialize Wire"); + + return false; + } + + // if (enableInsights) { + // insightsInit(applicationInsightsKey); + // } + + // Indicate that setup was successful + return true; +} + +void deviceLoop() { + const char *logTag = __func__; + + if (enableSerialConfiguration) { + logDebug(logTag, "Handling serial input events"); + // serialHandleEvents(); + } + + if (enableHttpServer) { + logDebug(logTag, "Handling HTTP Server events"); + // httpServerHandleEvents(); + } + + // Update display + const char *lines[4] = {"Line 1", "Line 2", "Line 3", "Line 4"}; + displayUpdate(lines); +} + +void deviceInformation() { + const char *logTag = __func__; + + // TODO(ksatirli) add code here +} diff --git a/src/Device.h b/src/Device.h new file mode 100644 index 0000000..daa4d1e --- /dev/null +++ b/src/Device.h @@ -0,0 +1,35 @@ +#ifndef DEVICE_H_ +#define DEVICE_H_ + +// Built-in and Third-Party libraries +#include +#include +#include + +/** + * @brief Retrieves device identifier + * + * This function retrieves a unique device identifier and formats it for downstream use + * + * @param length The length of the string to return. + * + * @return The text representation of the device identifier + */ +char *deviceIdentifier(int length = 16); + +/** + * @brief Initializes the `setup` stage. + */ +bool deviceSetup(); + +/** + * @brief Executes the `loop` stage. + */ +void deviceLoop(); + +/** + * @brief Gathers device information from ESP32 module. +*/ +void deviceInformation(); + +#endif // DEVICE_H_ From dd61c54a1833e78664f6a19641d718045fe45f19 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 22:21:28 +0200 Subject: [PATCH 13/74] adds Logging functions --- src/Log.cpp | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/Log.h | 101 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 src/Log.cpp create mode 100644 src/Log.h diff --git a/src/Log.cpp b/src/Log.cpp new file mode 100644 index 0000000..dc39c67 --- /dev/null +++ b/src/Log.cpp @@ -0,0 +1,120 @@ +#include "Log.h" + +//////////////////////////////////////////////////////////////////////////////// +// CONFIGURATION // +//////////////////////////////////////////////////////////////////////////////// + +// initialize log line buffer +constexpr size_t kLogLineBufferSize = 128; + +// TODO(ksatirli): Set global log level from CORE_DEBUG_LEVEL +// ⚠️ Levels `LOG_INFO`, `LOG_DEBUG`, and `LOG_VERBOSE` may result in a performance decrease +int logLevelGlobal = LOG_ERROR; + +// Define log levels and their corresponding integer values +const LogLevelMap logLevels[] = { + {"NONE", LOG_NONE }, + {"ERROR", LOG_ERROR }, + {"WARN", LOG_WARN }, + {"INFO", LOG_INFO }, + {"DEBUG", LOG_DEBUG }, + {"VERBOSE", LOG_VERBOSE} +}; + +const int logLevelsSize = sizeof(logLevels) / sizeof(LogLevelMap); + +//////////////////////////////////////////////////////////////////////////////// + +const char *getLogLevelName(LogLevel level) { + for (int i = 0; i < logLevelsSize; i++) { + if (logLevels[i].level == level) { + return logLevels[i].name; + } + } + + // Return "UNKNOWN" if the level is not found + return "UNKNOWN"; +} + +void logPrintSerialLine(LogLevel level, const char *glyph, const char *tag, const char *logMessage, va_list args) { + // Debug print to check log levels + // Serial.printf("logLevelGlobal: %d, level: %d\n", logLevelGlobal, level); + + // Check if serial connection is available and only continue if `level` is higher than globally set log level + if (Serial) { + // TODO(ksatirli) fix this + // if (Serial && level <= logLevelGlobal) { + // Create buffer for log line content + char logLine[kLogLineBufferSize]; + + // Handle variable arguments + vsnprintf(logLine, sizeof(logLine), logMessage, args); + + // Send assembled log line to serial output + Serial.printf("[%s][%s %s] %s\n", tag, glyph, getLogLevelName(level), logLine); + } +} + +void logDebug(const char *logTag, const char *logMessage, ...) { + // Handle variable arguments: + va_list args; + va_start(args, logMessage); + + // Assemble log line: + logPrintSerialLine(LOG_DEBUG, "🟦", logTag, logMessage, args); + + va_end(args); +} + +void logError(const char *logTag, const char *logMessage, ...) { + // Handle variable arguments: + va_list args; + va_start(args, logMessage); + + // Assemble log line: + logPrintSerialLine(LOG_ERROR, "🟥", logTag, logMessage, args); + + va_end(args); +} + +void logInfo(const char *logTag, const char *logMessage, ...) { + // Handle variable arguments: + va_list args; + va_start(args, logMessage); + + // Assemble log line: + logPrintSerialLine(LOG_INFO, "🟩", logTag, logMessage, args); + + va_end(args); +} + +void logWarning(const char *logTag, const char *logMessage, ...) { + // Handle variable arguments: + va_list args; + va_start(args, logMessage); + + // Assemble log line: + logPrintSerialLine(LOG_WARN, "🟨", logTag, logMessage, args); + + va_end(args); +} + +void logVerbose(const char *logTag, const char *logMessage, ...) { + // Handle variable arguments: + va_list args; + va_start(args, logMessage); + + // Assemble log line: + logPrintSerialLine(LOG_VERBOSE, "⬛", logTag, logMessage, args); + + va_end(args); +} + +void logSetLevel(LogLevel level) { + const char *logTag = __func__; + + logInfo(logTag, "Setting log level to %d", level); + + // Update global log level + logLevelGlobal = level; +} diff --git a/src/Log.h b/src/Log.h new file mode 100644 index 0000000..a4c5a4c --- /dev/null +++ b/src/Log.h @@ -0,0 +1,101 @@ +#ifndef LOG_H_ +#define LOG_H_ + +#include + +#include +#include + +//////////////////////////////////////////////////////////////////////////////// +// CONFIGURATION // +//////////////////////////////////////////////////////////////////////////////// + +extern const size_t kLogLineBufferSize; + +typedef enum { LOG_NONE = 0, LOG_ERROR = 1, LOG_WARN = 2, LOG_INFO = 3, LOG_DEBUG = 4, LOG_VERBOSE = 5 } LogLevel; + +struct LogLevelMap { + const char *name; + LogLevel level; +}; + +extern int logLevelGlobal; + +extern const LogLevelMap logLevels[]; + +extern const int logLevelsSize; +//////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Converts a numeric log level to its corresponding string representation. + * + * @param level The numeric log level. + * + * @return The string representation of the log level. + */ +const char *getLogLevelName(LogLevel level); + +/** + * @brief Prints a log message to the serial output. + * + * @param level The level of the log message. + * @param glyph The emoji representing the log level. + * @param tag The tag identifying the log source. + * @param logMessage The log message format string. + * @param ... Additional arguments to format the log message. + */ +void logPrintSerialLine(LogLevel level, const char *glyph, const char *tag, const char *logMessage, ...); + +/** + * @brief Logs a message at `DEBUG` level. + * + * @param logTag The tag identifying the log source. + * @param logMessage The log message format string. + * @param ... Additional arguments to format the log message. + */ +void logDebug(const char *logTag, const char *logMessage, ...); + +/** + * @brief Logs a message at `ERROR` level. + * + * @param logTag The tag identifying the log source. + * @param logMessage The log message format string. + * @param ... Additional arguments to format the log message. + */ +void logError(const char *logTag, const char *logMessage, ...); + +/** + * @brief Logs a message at `INFO` level. + * + * @param logTag The tag identifying the log source. + * @param logMessage The log message format string. + * @param ... Additional arguments to format the log message. + */ +void logInfo(const char *logTag, const char *logMessage, ...); + +/** + * @brief Logs a message at `WARN` level. + * + * @param logTag The tag identifying the log source. + * @param logMessage The log message format string. + * @param ... Additional arguments to format the log message. + */ +void logWarning(const char *logTag, const char *logMessage, ...); + +/** + * @brief Logs a message at `VERBOSE` level. + * + * @param logTag The tag identifying the log source. + * @param logMessage The log message format string. + * @param ... Additional arguments to format the log message. + */ +void logVerbose(const char *logTag, const char *logMessage, ...); + +/** + * @brief Updates the global log level setting. + * + * @param level The new log level. + */ +void logSetLevel(LogLevel level); + +#endif // LOG_H_ From 3fe050a9a3d16f4a86bdedd98ef4a3b0c82c25df Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 22:21:43 +0200 Subject: [PATCH 14/74] work-up for Wi-Fi and Wire clients --- src/WifiClient.cpp | 246 +++++++++++++++++++++++++++++++++++++++++++++ src/WifiClient.h | 56 +++++++++++ src/WireClient.cpp | 24 +++++ src/WireClient.h | 12 +++ 4 files changed, 338 insertions(+) create mode 100644 src/WifiClient.cpp create mode 100644 src/WifiClient.h create mode 100644 src/WireClient.cpp create mode 100644 src/WireClient.h diff --git a/src/WifiClient.cpp b/src/WifiClient.cpp new file mode 100644 index 0000000..da9f509 --- /dev/null +++ b/src/WifiClient.cpp @@ -0,0 +1,246 @@ +#include "WifiClient.h" + +#include "Device.h" +#include "Helpers.h" +#include "Log.h" + +//////////////////////////////////////////////////////////////////////////////// +// CONFIGURATION // +//////////////////////////////////////////////////////////////////////////////// + +// Toggle to enable auto-reconnect to Wi-Fi +const bool wifiAutoReconnect = true; + +// How many milliseconds to delay after disconnect +const int wifiDisconnectDelay = 1000; + +// Wi-Fi hostname prefix +// Must not be longer than 27 characters, as 5 characters +// are reserved for the device identifier and a separator) +const char *wifiHostnamePrefix = "pathfinder"; + +// Wi-Fi hostname +char wifiHostname[32]; + +// Wi-Fi / mDNS instance name +const char *wifiInstanceName = "Pathfinder"; + +// Wi-Fi password +char wifiPassword[64] = "workloads"; + +// Wi-Fi Protected Access Mode +const char wifiProtectedAccessMode[32] = "WPA2"; + +// How many times to attempt to connect to Wi-Fi +int wifiReconnectAttempts = 20; + +// How many milliseconds to delay before attempting reconnection +const int wifiReconnectDelay = 1000; + +// How many milliseconds to delay the next Wi-Fi scan +const int wifiRescanDelay = 10000; + +// TODO(ksatirli): load from config file +// Wi-Fi SSID (network name) +char wifiSsid[32] = "workloads"; + +// Toggle for hidden Wi-Fi SSID +const bool wifiSsidHidden = false; + +// How many milliseconds to delay between status messages +const int wifiStatusMessageDelay = 500; +//////////////////////////////////////////////////////////////////////////////// + +char *wifiGenerateHostname() { + const char *logTag = __func__; + + // Static storage to ensure the string remains valid after the function returns + static char wifiHostname[32]; + + // Get the device identifier + char *deviceId = deviceIdentifier(4); + + // Assemble the Wi-Fi hostname + snprintf(wifiHostname, sizeof(wifiHostname), "%s-%s", wifiHostnamePrefix, deviceId); + + logDebug(logTag, "Generated hostname: `%s`", wifiHostname); + + return strdup(wifiHostname); +} + +bool wifiDisconnect() { + const char *logTag = __func__; + + logInfo(logTag, "Disconnecting from SSID `%s`", wifiSsid); + + // First `false` = do not turn Wi-Fi radio off + // Second `false` = do not erase Wi-Fi AP data + // See https://docs.espressif.com/projects/arduino-esp32/en/latest/api/wifi.html#disconnect + WiFi.disconnect(false, false); + + // Block flow and allow for cleanup + delay(wifiDisconnectDelay); + + // Since WiFi.disconnect() does not provide a return value, assume success + return true; +} + +bool wifiConnect() { + const char *logTag = __func__; + + logDebug(logTag, "Generating Wi-Fi hostname"); + char *wifiHostname = wifiGenerateHostname(); + + // Set Wi-Fi hostname + logDebug(logTag, "Setting Wi-Fi hostname to `%s`", wifiHostname); + WiFi.setHostname(wifiHostname); + + // Set Wi-Fi auto-reconnect option + const char *wifiAutoReconnectStr = wifiAutoReconnect ? "true" : "false"; + logDebug(logTag, "Setting Wi-Fi auto-reconnect option to `%s`", wifiAutoReconnectStr); + WiFi.setAutoReconnect(wifiAutoReconnect); + + // Set Wi-Fi mode + // TODO(ksatirli): move to variables? + WiFi.mode(WIFI_STA); + + // Initialize Wi-Fi connection + WiFi.begin(wifiSsid, wifiPassword); + logInfo(logTag, "Attempting to connect to SSID `%s`", wifiSsid); + + // Try to establish a connection with a limited number of retries + int attemptsLeft = wifiReconnectAttempts; + + while (attemptsLeft > 0) { + // Check the connection status after a delay + delay(wifiReconnectDelay); + int attemptCount = wifiReconnectAttempts - attemptsLeft + 1; + + switch (WiFi.status()) { + case WL_NO_SHIELD: + logError(logTag, "Device unable to find Radio"); + return false; + + case WL_NO_SSID_AVAIL: + logInfo(logTag, "Device unable to find SSID `%s` after %d attempts", wifiSsid, attemptCount); + break; + + case WL_CONNECT_FAILED: + logWarning(logTag, "Device unable to connect"); + break; + + case WL_CONNECTION_LOST: + logInfo(logTag, "Device lost connection"); + break; + + case WL_SCAN_COMPLETED: + logDebug(logTag, "Device completed scan"); + break; + + case WL_DISCONNECTED: + logInfo(logTag, "Device disconnected"); + break; + + case WL_CONNECTED: + logInfo(logTag, "Device connected with IP `%s`", WiFi.localIP().toString().c_str()); + + // Connection established, start mDNS service + wifiStartMdnsService(wifiHostname, wifiInstanceName); + + return true; + + default: + logWarning(logTag, "Unhandled Wi-Fi status `%d` on attempt %d", WiFi.status(), attemptCount); + break; + } + + // Decrement attempts after processing status + attemptsLeft--; + + if (attemptsLeft <= 0) { + logError(logTag, "Failed to connect to SSID `%s` after %d attempts", wifiSsid, wifiReconnectAttempts); + wifiDisconnect(); + + return false; + } + } + + return false; +} + +bool wifiConnectionAlive() { + return WiFi.status() == WL_CONNECTED; +} + +void wifiReconnect() { + const char *logTag = __func__; + + logInfo(logTag, "Disconnecting from Wi-Fi"); + wifiDisconnect(); + + logInfo(logTag, "Reconnecting to Wi-Fi SSID `%s`", wifiSsid); + WiFi.reconnect(); + + // Print to serial monitor while connection status is not "connected" + while (WiFi.status() != WL_CONNECTED) { + delay(wifiStatusMessageDelay); + Serial.print("."); + } + + // Once connected, log the new IP address + const char *ipAddress = helperIpAddressToString(WiFi.localIP()); + logInfo(logTag, "Connected with IP `%s`", ipAddress); + // As ipAddress is returned from helperIpAddressToString, no need for manual memory management here +} + +void wifiScanNetworks() { + const char *logTag = __func__; + + // Start Wi-Fi scan + // See https://www.arduino.cc/reference/en/libraries/wifi/wifi.scannetworks/ + logInfo(logTag, "Starting Wi-Fi scan"); + int networkCount = WiFi.scanNetworks(); + + // Check if Wi-Fi scan was successful + if (networkCount == -1) { + logError(logTag, "Failed to complete Wi-Fi scan"); + } else { + logInfo(logTag, "Wi-Fi scan completed, found %d networks", networkCount); + + // Log details of found networks + for (int i = 0; i < networkCount; i++) { + // clang-format off + logInfo(logTag, + "%d: `%s` (RSSI: %d, Encryption: %s)", + i + 1, + WiFi.SSID(i).c_str(), + WiFi.RSSI(i), + (WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? "🔓" : "🔒"); + // clang-format on + } + } + + // Wait a bit before scanning again + delay(wifiRescanDelay); +} + +void wifiStartMdnsService(const char *hostname, const char *instance_name) { + const char *logTag = __func__; + + // Initialize mDNS service + logDebug(logTag, "Initializing mDNS service"); + esp_err_t err = mdns_init(); + + if (err) { + // TODO(ksatirli): add `err` to log message + logError(logTag, "Failed to initialize mDNS: %s", esp_err_to_name(err)); + + return; + } + + logDebug(logTag, "Setting mDNS hostname to `%s`", hostname); + mdns_hostname_set(hostname); + + logDebug(logTag, "Setting mDNS instance name to `%s`", instance_name); + mdns_instance_name_set(instance_name); +} diff --git a/src/WifiClient.h b/src/WifiClient.h new file mode 100644 index 0000000..848d8c4 --- /dev/null +++ b/src/WifiClient.h @@ -0,0 +1,56 @@ +#ifndef WIFICLIENT_H_ +#define WIFICLIENT_H_ + +// Built-in and Third-Party libraries +#include +#include + +/** + * @brief Generate Wi-Fi hostname. + * + * @return nil if the hostname was generated successfully + */ +char *wifiGenerateHostname(); + +/** + * @brief Disconnect from a Wi-Fi network. + * @return True if the disconnection was successful, false otherwise. + */ +bool wifiDisconnect(); + +/** + * @brief Establish connection with a Wi-Fi network. + * + * @return True if the connection was successful, false otherwise. + * @note This function has the device acting as a client (= station). + */ +bool wifiConnect(); + +/** + * @brief Check if the Wi-Fi connection is alive. + * + * @return True if the connection is alive, false otherwise. + */ +bool wifiConnectionAlive(); + +/** + * @brief Reestablish connection with a Wi-Fi network. + * + * @note This function has the device acting as a client (= station). + */ +void wifiReconnect(); + +/** + * @brief Scan for Wi-Fi networks. + */ +void wifiScanNetworks(); + +/** + * @brief Start mDNS service. + * + * @param hostname The hostname to use. + * @param instance_name The instance name to use. + */ +void wifiStartMdnsService(const char *hostname, const char *instance_name); + +#endif // WIFICLIENT_H_ diff --git a/src/WireClient.cpp b/src/WireClient.cpp new file mode 100644 index 0000000..8643f7c --- /dev/null +++ b/src/WireClient.cpp @@ -0,0 +1,24 @@ +#include "WireClient.h" + +#include "Log.h" + +//////////////////////////////////////////////////////////////////////////////// +// CONFIGURATION // +//////////////////////////////////////////////////////////////////////////////// + +#define S_SCL 33 +#define S_SDA 32 +//////////////////////////////////////////////////////////////////////////////// + +bool wireInit() { + const char *logTag = __func__; + + // See https://www.arduino.cc/reference/en/language/functions/communication/wire/begin/ + if (!Wire.begin(S_SDA, S_SCL)) { + logError(logTag, "Failed to initialize Wire"); + + return false; + } + + return true; +} diff --git a/src/WireClient.h b/src/WireClient.h new file mode 100644 index 0000000..d0d75f2 --- /dev/null +++ b/src/WireClient.h @@ -0,0 +1,12 @@ +#ifndef WIRECLIENT_H_ +#define WIRECLIENT_H_ + +// Built-in and Third-Party libraries +#include + +/** + * @brief Initializes the Wire + */ +bool wireInit(); + +#endif // WIRECLIENT_H_ From 3c5efff6a7e081bb7d4a7640443ae88569f62d1e Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 22:22:47 +0200 Subject: [PATCH 15/74] work-up for Display refactor --- src/Display.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ src/Display.h | 21 ++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 src/Display.cpp create mode 100644 src/Display.h diff --git a/src/Display.cpp b/src/Display.cpp new file mode 100644 index 0000000..f85770c --- /dev/null +++ b/src/Display.cpp @@ -0,0 +1,73 @@ +#include "Display.h" + +#include "Log.h" + +//////////////////////////////////////////////////////////////////////////////// +// CONFIGURATION // +//////////////////////////////////////////////////////////////////////////////// + +// Display height and width (in pixels) +const uint8_t displayHeight = 128; +const uint8_t displayWidth = 32; + +// See https://github.com/adafruit/Adafruit_SSD1306/blob/master/Adafruit_SSD1306.h for color overview +const uint16_t displayTextColor = SSD1306_WHITE; + +const uint8_t displayTextSize = 1; + +// Display Reset Pin (or `-1` if shared with Arduino Reset Pin) +const int8_t displayResetPin = -1; + +// 128 x 32 display = `0x3C` +// 128 x 64 display = `0x3D` +const uint8_t displayAddress = 0x3C; + +// TODO(ksatirli) clean this up +// Default screen lines +char screenLine_0[50] = "Line 1"; +char screenLine_1[50] = "Line 2"; +char screenLine_2[50] = "Line 3"; +char screenLine_3[50] = "Line 4"; + +//////////////////////////////////////////////////////////////////////////////// + +// Initialize display library +Adafruit_SSD1306 display(displayWidth, displayHeight, &Wire, displayResetPin); + +bool displayInit() { + const char *logTag = __func__; + + // `SSD1306_SWITCHCAPVCC` = generate display voltage from 3.3V internal + if (!display.begin(SSD1306_SWITCHCAPVCC, displayAddress)) { + logError(logTag, "SSD1306 allocation failed"); + + return false; + } + + logDebug(logTag, "Clearing Display"); + display.clearDisplay(); + display.setCursor(0, 0); + display.setTextColor(displayTextColor); + display.setTextSize(displayTextSize); + + // Render image buffer on the display + logDebug(logTag, "Rendering Image Buffer"); + display.display(); + + return true; +} + +void displayUpdate(const char *lines[4]) { + const char *logTag = __func__; + + logDebug(logTag, "Clearing display"); + display.clearDisplay(); + display.setCursor(0, 0); + + for (int i = 0; i < 4; ++i) { + display.println(lines[i]); + } + + logDebug(logTag, "Rendering lines"); + display.display(); +} diff --git a/src/Display.h b/src/Display.h new file mode 100644 index 0000000..fd818fd --- /dev/null +++ b/src/Display.h @@ -0,0 +1,21 @@ +#ifndef DISPLAY_H_ +#define DISPLAY_H_ + +// Built-in and Third-Party libraries +#include +#include +#include + +/** + * @brief Initializes the OLED display. + */ +bool displayInit(); + +/** + * @brief Updates the OLED display with the provided screen lines. + * + * @param lines array of strings to be displayed on the screen. + */ +void displayUpdate(const char *lines[4]); + +#endif // DISPLAY_H_ From 418e45b535e01af07c2c107e82a0b3cbde58fe35 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 22:33:30 +0200 Subject: [PATCH 16/74] adds Ministache --- README.md | 2 +- config.mk | 1 + sketch.yml | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 07b5ab4..c8727f4 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ _selfcheck lint Makefile `make _selfchec This repository does not include any datasheets directly. -* for the Waveshare WAVE ROVER`, see [waveshare.com](https://www.waveshare.com/wiki/WAVE_ROVER#Resource) +* for the Waveshare WAVE ROVER, see [waveshare.com](https://www.waveshare.com/wiki/WAVE_ROVER#Resource) * for the Waveshare OLED module, see [waveshare.com](https://www.waveshare.com/wiki/0.91inch_OLED_Module) * for the ESP32 `WROOM-32UE-N4` module, see [espressif.com](https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32e_esp32-wroom-32ue_datasheet_en.pdf) diff --git a/config.mk b/config.mk index e5bf649..458486a 100644 --- a/config.mk +++ b/config.mk @@ -36,6 +36,7 @@ ARDUINO_LIBRARIES_UPSTREAM ?= \ "ICM20948_WE@1.1.8" \ "INA219_WE@1.3.8" \ "LittleFS_esp32@1.0.6" \ + "Ministache@1.0.1" \ "PID_v2@2.0.1" \ "SCServo@1.0.2" \ "SimpleKalmanFilter@0.1" diff --git a/sketch.yml b/sketch.yml index 4023fed..757d967 100644 --- a/sketch.yml +++ b/sketch.yml @@ -73,6 +73,10 @@ profiles: # see https://github.com/lorol/LITTLEFS LittleFS_esp32 (1.0.6) + - + # see https://github.com/floatplane/ministache + Ministache (1.0.1) + - # see https://github.com/imax9000/Arduino-PID-Library PID_v2 (2.0.1) From 379494ef68ebf69b4f8b2b43b1319f1323c79a88 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 22:37:49 +0200 Subject: [PATCH 17/74] linting --- README.md | 2 ++ src/Device.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c8727f4..f214a5f 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,8 @@ docs-get-theme retrieve Doxygen theme using git `make docs-get- help display a list of Make Targets `make help` _listincludes list all included Makefiles and *.mk files `make _listincludes` _selfcheck lint Makefile `make _selfcheck` +vale lint prose with Vale `make vale` +vale-sync sync Vale dependencies `make vale-sync` ``` ## Notes diff --git a/src/Device.cpp b/src/Device.cpp index 609f4f7..243d8a2 100644 --- a/src/Device.cpp +++ b/src/Device.cpp @@ -16,7 +16,7 @@ char applicationCompilationString[32]; // TODO(ksatirli) move this to a configuration file // see https://dashboard.insights.espressif.com/home/manage-auth-keys/ -const char applicationInsightsKey[] = ""; +const char applicationInsightsKey[] = ""; // Toggle to sleep HTTP Server const bool enableHttpServer = false; From 9b777eff674fc7a64d7b848c31a3d348b664f957 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 22:38:52 +0200 Subject: [PATCH 18/74] refactors main sketch --- pathfinder.ino | 267 ++++--------------------------------------------- 1 file changed, 21 insertions(+), 246 deletions(-) diff --git a/pathfinder.ino b/pathfinder.ino index b97423e..968af44 100644 --- a/pathfinder.ino +++ b/pathfinder.ino @@ -7,267 +7,42 @@ * */ -#ifndef CORE_DEBUG_LEVEL -// ⚠️ Levels `LOG_INFO`, `LOG_DEBUG`, and `LOG_VERBOSE` may result in a performance decrease -#define CORE_DEBUG_LEVEL LOG_ERROR -#endif +//////////////////////////////////////////////////////////////////////////////// +// CONFIGURATION // +//////////////////////////////////////////////////////////////////////////////// -// TaskHandle_t Pid_ctrl; +// How many milliseconds to delay before restarting `setup()` +const int deviceSetupRestartDelay = 3000; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -StaticJsonDocument<256> jsonCmdReceive; -StaticJsonDocument<256> jsonInfoSend; -StaticJsonDocument<512> jsonInfoHttp; +// Baud rate to use for serial communication +const int serialBaudRate = 115200; +//////////////////////////////////////////////////////////////////////////////// // Load local configuration and helpers -#include "src/Battery.h" -#include "src/ugv_config.h" -#include "src/oled_ctrl.h" -#include "src/PinController.h" -#include "src/RoArm-M2_module.h" -#include "src/gimbal_module.h" -#include "src/json_cmd.h" -#include "src/IMU_ctrl.h" -#include "src/Movement.h" -#include "src/files_ctrl.h" -#include "src/ugv_advance.h" -#include "src/wifi_ctrl.h" -#include "src/esp_now_ctrl.h" -#include "src/uart_ctrl.h" -#include "src/HttpServer.h" - -void moduleType_Gimbal() { - getGimbalFeedback(); - gimbalSteady(steadyGoalY); -} - +#include "src/Device.h" +#include "src/Log.h" // Setup application flow void setup() { - Serial.begin(115200); - Wire.begin(S_SDA, S_SCL); - - while (!Serial) { - } - - ina219_init(); - inaDataUpdate(); - - // set mainType & moduleType. - // mainType: 1.WAVE ROVER, 2.UGV02, 3.UGV01 - // moduleType: 0.Null, 1.RoArm, 2.PT - mm_settings(mainType, moduleType); - - init_oled(); - - if (mainType == 1) { - screenLine_0 = "WAVE ROVER"; - } else if (mainType == 2) { - screenLine_0 = "UGV"; - } else if (mainType == 3) { - screenLine_0 = "UGV"; - } - - screenLine_1 = "version: 0.95"; - screenLine_2 = "starting..."; - screenLine_3 = ""; - oled_update(); - - delay(1200); - - // functions for IMU. - imu_init(); - - // functions for the LEDs on ugv. - PinControllerInit(); + const char *logTag = __func__; - // init the littleFS functions in files_ctrl.h - screenLine_2 = screenLine_3; - screenLine_3 = "Initialize LittleFS"; - oled_update(); + Serial.begin(serialBaudRate); - if (InfoPrint == 1) { - Serial.println("Initialize LittleFS for Flash files ctrl."); - } - - initFS(); - - // init the functions in switch_module.h - screenLine_2 = screenLine_3; - screenLine_3 = "Initialize 12V-switch ctrl"; - oled_update(); - - if (InfoPrint == 1) { - Serial.println("Initialize the pins used for 12V-switch ctrl."); - } + Serial.println("Serial connection initialized"); - movtionPinInit(); + logDebug(logTag, "Initializing device setup"); - // servos power up - screenLine_2 = screenLine_3; - screenLine_3 = "Power up the servos"; - oled_update(); + while (!deviceSetup()) { + logWarning(logTag, "Device setup failed, retrying in %d seconds...", deviceSetupRestartDelay / 1000); // NOLINT(whitespace/line_length) - if (InfoPrint == 1) { - Serial.println("Power up the servos."); + // delay restart of `setup()` so device and ecosystem (e.g.: Wi-Fi APs) + // have enough time to process operations and restore connectivity + // see https://www.arduino.cc/reference/en/language/functions/time/delay/ + delay(deviceSetupRestartDelay); } - - delay(500); - - // init servo ctrl functions. - screenLine_2 = screenLine_3; - screenLine_3 = "ServoCtrl init UART2TTL..."; - oled_update(); - - if (InfoPrint == 1) { - Serial.println("ServoCtrl init UART2TTL..."); - } - - // check the status of the servos. - screenLine_2 = screenLine_3; - screenLine_3 = "Bus servos status check..."; - oled_update(); - - if (InfoPrint == 1) { - Serial.println("Bus servos status check..."); - } - - if (InfoPrint == 1) { - Serial.println("All bus servos status checked."); - } - - screenLine_3 = ">>> Moving to init pos..."; - oled_update(); - - screenLine_3 = "Reset joint torque to ST_TORQUE_MAX"; - oled_update(); - - if (InfoPrint == 1) { - Serial.println("Reset joint torque to ST_TORQUE_MAX."); - } - - screenLine_3 = "WiFi init"; - oled_update(); - - if (InfoPrint == 1) { - Serial.println("WiFi init."); - } - - initWifi(); - - screenLine_3 = "http & web init"; - oled_update(); - - if (InfoPrint == 1) { - Serial.println("http & web init."); - } - - httpServerInit(); - - screenLine_3 = "ESP-NOW init"; - oled_update(); - - if (InfoPrint == 1) { - Serial.println("ESP-NOW init."); - } - - initEspNow(); - - screenLine_3 = "IMU Calibrating"; - oled_update(); - - if (InfoPrint == 1) { - Serial.println("IMU Calibrating"); - } - - imuCalibration(); - - screenLine_3 = "UGV started"; - oled_update(); - - if (InfoPrint == 1) { - Serial.println("UGV started."); - } - - getThisDevMacAddress(); - - updateOledWifiInfo(); - - initEncoders(); - - pidControllerInit(); - - screenLine_2 = String("MAC:") + macToString(thisDevMac); - oled_update(); - - led_pwm_ctrl(0, 0); - - if (InfoPrint == 1) { - Serial.println("Application initialization settings."); - } - - createMission("boot", "these cmds run automatically at boot."); - missionPlay("boot", 1); } - // Enter application flow void loop() { - serialCtrl(); - server.handleClient(); - - // read and compute the info of joints. - switch (moduleType) { - case 1: - // RoArm 2 - break; - - case 2: - moduleType_Gimbal(); - break; - } - - // receive esp-now json cmd. - if (runNewJsonCmd) { - jsonCmdReceiveHandler(); - jsonCmdReceive.clear(); - runNewJsonCmd = false; - } - - getLeftSpeed(); - - LeftPidControllerCompute(); - - getRightSpeed(); - - RightPidControllerCompute(); - - oledInfoUpdate(); - - updateIMUData(); - - if (baseFeedbackFlow) { - baseInfoFeedback(); - } - - heartBeatCtrl(); - - size_t freeHeap = esp_get_free_heap_size(); + deviceLoop(); } From 1199937203c53b0ba5376702e70a7a8dffc2f16c Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 22:48:31 +0200 Subject: [PATCH 19/74] linting --- README.md | 4 ++-- pathfinder.ino | 4 ++-- src/Log.h | 5 +++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f214a5f..6cec7a1 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# Pathfinder +# 🧭 Pathfinder > ESP32-based mobile edge computing device based on the Waveshare UGV platform ## Table of Contents -* [Pathfinder](#pathfinder) +* [🧭 Pathfinder](#-pathfinder) * [Table of Contents](#table-of-contents) * [Requirements](#requirements) * [Hardware](#hardware) diff --git a/pathfinder.ino b/pathfinder.ino index 968af44..fe23f78 100644 --- a/pathfinder.ino +++ b/pathfinder.ino @@ -26,8 +26,8 @@ const int serialBaudRate = 115200; void setup() { const char *logTag = __func__; + // Initialize serial communication Serial.begin(serialBaudRate); - Serial.println("Serial connection initialized"); logDebug(logTag, "Initializing device setup"); @@ -35,7 +35,7 @@ void setup() { while (!deviceSetup()) { logWarning(logTag, "Device setup failed, retrying in %d seconds...", deviceSetupRestartDelay / 1000); // NOLINT(whitespace/line_length) - // delay restart of `setup()` so device and ecosystem (e.g.: Wi-Fi APs) + // Delay restart of `setup()` so device and ecosystem (e.g.: Wi-Fi APs) // have enough time to process operations and restore connectivity // see https://www.arduino.cc/reference/en/language/functions/time/delay/ delay(deviceSetupRestartDelay); diff --git a/src/Log.h b/src/Log.h index a4c5a4c..dcc2cb1 100644 --- a/src/Log.h +++ b/src/Log.h @@ -12,17 +12,22 @@ extern const size_t kLogLineBufferSize; +// Log levels enumeration typedef enum { LOG_NONE = 0, LOG_ERROR = 1, LOG_WARN = 2, LOG_INFO = 3, LOG_DEBUG = 4, LOG_VERBOSE = 5 } LogLevel; +// Mapping of log level names to their corresponding log level values struct LogLevelMap { const char *name; LogLevel level; }; +// Global log level setting extern int logLevelGlobal; +// Array of log level mappings extern const LogLevelMap logLevels[]; +// Size of the log levels array extern const int logLevelsSize; //////////////////////////////////////////////////////////////////////////////// From 3e0d29b188fe15226a455de0532ff61de6bbea11 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 22:58:06 +0200 Subject: [PATCH 20/74] adds docs --- src/Log.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/src/Log.cpp b/src/Log.cpp index dc39c67..41c7ca2 100644 --- a/src/Log.cpp +++ b/src/Log.cpp @@ -4,7 +4,7 @@ // CONFIGURATION // //////////////////////////////////////////////////////////////////////////////// -// initialize log line buffer +// Initialize log line buffer constexpr size_t kLogLineBufferSize = 128; // TODO(ksatirli): Set global log level from CORE_DEBUG_LEVEL @@ -25,6 +25,13 @@ const int logLevelsSize = sizeof(logLevels) / sizeof(LogLevelMap); //////////////////////////////////////////////////////////////////////////////// +/** + * @brief Converts a numeric log level to its corresponding string representation. + * + * @param level The numeric log level. + * + * @return The string representation of the log level. + */ const char *getLogLevelName(LogLevel level) { for (int i = 0; i < logLevelsSize; i++) { if (logLevels[i].level == level) { @@ -36,6 +43,15 @@ const char *getLogLevelName(LogLevel level) { return "UNKNOWN"; } +/** + * @brief Prints a log message to the serial output. + * + * @param level The level of the log message. + * @param glyph The emoji representing the log level. + * @param tag The tag identifying the log source. + * @param logMessage The log message format string. + * @param args Additional arguments to format the log message. + */ void logPrintSerialLine(LogLevel level, const char *glyph, const char *tag, const char *logMessage, va_list args) { // Debug print to check log levels // Serial.printf("logLevelGlobal: %d, level: %d\n", logLevelGlobal, level); @@ -55,6 +71,13 @@ void logPrintSerialLine(LogLevel level, const char *glyph, const char *tag, cons } } +/** + * @brief Logs a message at `DEBUG` level. + * + * @param logTag The tag identifying the log source. + * @param logMessage The log message format string. + * @param ... Additional arguments to format the log message. + */ void logDebug(const char *logTag, const char *logMessage, ...) { // Handle variable arguments: va_list args; @@ -66,6 +89,13 @@ void logDebug(const char *logTag, const char *logMessage, ...) { va_end(args); } +/** + * @brief Logs a message at `ERROR` level. + * + * @param logTag The tag identifying the log source. + * @param logMessage The log message format string. + * @param ... Additional arguments to format the log message. + */ void logError(const char *logTag, const char *logMessage, ...) { // Handle variable arguments: va_list args; @@ -77,6 +107,13 @@ void logError(const char *logTag, const char *logMessage, ...) { va_end(args); } +/** + * @brief Logs a message at `INFO` level. + * + * @param logTag The tag identifying the log source. + * @param logMessage The log message format string. + * @param ... Additional arguments to format the log message. + */ void logInfo(const char *logTag, const char *logMessage, ...) { // Handle variable arguments: va_list args; @@ -88,6 +125,13 @@ void logInfo(const char *logTag, const char *logMessage, ...) { va_end(args); } +/** + * @brief Logs a message at `WARN` level. + * + * @param logTag The tag identifying the log source. + * @param logMessage The log message format string. + * @param ... Additional arguments to format the log message. + */ void logWarning(const char *logTag, const char *logMessage, ...) { // Handle variable arguments: va_list args; @@ -99,6 +143,13 @@ void logWarning(const char *logTag, const char *logMessage, ...) { va_end(args); } +/** + * @brief Logs a message at `VERBOSE` level. + * + * @param logTag The tag identifying the log source. + * @param logMessage The log message format string. + * @param ... Additional arguments to format the log message. + */ void logVerbose(const char *logTag, const char *logMessage, ...) { // Handle variable arguments: va_list args; @@ -110,6 +161,11 @@ void logVerbose(const char *logTag, const char *logMessage, ...) { va_end(args); } +/** + * @brief Updates the global log level setting. + * + * @param level The new log level. + */ void logSetLevel(LogLevel level) { const char *logTag = __func__; From 177874912d4da9f3e214c15c5393ccd7ab6a0bb8 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 22:59:09 +0200 Subject: [PATCH 21/74] linting --- src/Log.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Log.cpp b/src/Log.cpp index 41c7ca2..b9b7110 100644 --- a/src/Log.cpp +++ b/src/Log.cpp @@ -53,9 +53,6 @@ const char *getLogLevelName(LogLevel level) { * @param args Additional arguments to format the log message. */ void logPrintSerialLine(LogLevel level, const char *glyph, const char *tag, const char *logMessage, va_list args) { - // Debug print to check log levels - // Serial.printf("logLevelGlobal: %d, level: %d\n", logLevelGlobal, level); - // Check if serial connection is available and only continue if `level` is higher than globally set log level if (Serial) { // TODO(ksatirli) fix this From 687692ae911193cf909b48fa08e8865a4915cf24 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 23:11:23 +0200 Subject: [PATCH 22/74] linting --- src/WifiClient.cpp | 21 ++++++++++----------- src/WifiClient.h | 1 + 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/WifiClient.cpp b/src/WifiClient.cpp index da9f509..1cd2927 100644 --- a/src/WifiClient.cpp +++ b/src/WifiClient.cpp @@ -9,46 +9,46 @@ //////////////////////////////////////////////////////////////////////////////// // Toggle to enable auto-reconnect to Wi-Fi -const bool wifiAutoReconnect = true; +constexpr bool wifiAutoReconnect = true; // How many milliseconds to delay after disconnect -const int wifiDisconnectDelay = 1000; +constexpr int wifiDisconnectDelay = 1000; // Wi-Fi hostname prefix // Must not be longer than 27 characters, as 5 characters // are reserved for the device identifier and a separator) -const char *wifiHostnamePrefix = "pathfinder"; +constexpr char wifiHostnamePrefix[] = "pathfinder"; // Wi-Fi hostname char wifiHostname[32]; // Wi-Fi / mDNS instance name -const char *wifiInstanceName = "Pathfinder"; +constexpr char wifiInstanceName[] = "Pathfinder"; // Wi-Fi password char wifiPassword[64] = "workloads"; // Wi-Fi Protected Access Mode -const char wifiProtectedAccessMode[32] = "WPA2"; +constexpr char wifiProtectedAccessMode[] = "WPA2"; // How many times to attempt to connect to Wi-Fi -int wifiReconnectAttempts = 20; +constexpr int wifiReconnectAttempts = 20; // How many milliseconds to delay before attempting reconnection -const int wifiReconnectDelay = 1000; +constexpr int wifiReconnectDelay = 1000; // How many milliseconds to delay the next Wi-Fi scan -const int wifiRescanDelay = 10000; +constexpr int wifiRescanDelay = 10000; // TODO(ksatirli): load from config file // Wi-Fi SSID (network name) char wifiSsid[32] = "workloads"; // Toggle for hidden Wi-Fi SSID -const bool wifiSsidHidden = false; +constexpr bool wifiSsidHidden = false; // How many milliseconds to delay between status messages -const int wifiStatusMessageDelay = 500; +constexpr int wifiStatusMessageDelay = 500; //////////////////////////////////////////////////////////////////////////////// char *wifiGenerateHostname() { @@ -234,7 +234,6 @@ void wifiStartMdnsService(const char *hostname, const char *instance_name) { if (err) { // TODO(ksatirli): add `err` to log message logError(logTag, "Failed to initialize mDNS: %s", esp_err_to_name(err)); - return; } diff --git a/src/WifiClient.h b/src/WifiClient.h index 848d8c4..d1fc4da 100644 --- a/src/WifiClient.h +++ b/src/WifiClient.h @@ -14,6 +14,7 @@ char *wifiGenerateHostname(); /** * @brief Disconnect from a Wi-Fi network. + * * @return True if the disconnection was successful, false otherwise. */ bool wifiDisconnect(); From 6dae77ec65818dbcbf9ed9790edf6083427b5542 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 23:15:21 +0200 Subject: [PATCH 23/74] linting --- src/Helpers.cpp | 43 +++++++++++++++++++++++++++++++++++++++---- src/Helpers.h | 7 ++++--- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/Helpers.cpp b/src/Helpers.cpp index 85e8271..afcbd97 100644 --- a/src/Helpers.cpp +++ b/src/Helpers.cpp @@ -2,12 +2,29 @@ #include "Log.h" -bool helperCheckIfStringStartsWithProtocol(const char *input) { + +/** + * @brief Checks if a string starts with a protocol. + * + * This function checks if the input string starts with a protocol, such as `http` or `https`. + * + * @param input The string to check. + * + * @return `true` if the string starts with a protocol, `false` otherwise. + */ +inline bool helperCheckIfStringStartsWithProtocol(const char *input) { // Check if input starts with "http" (includes "https") return strncmp(input, "http", 4) == 0; } -const char *helperIpAddressToString(IPAddress inputAddr) { +/** + * @brief Converts IP Address of type IPAddress to a string. + * + * @param inputAddr The IP Address to convert to a string. + * + * @return The string representation of the IP Address. + */ +inline const char *helperIpAddressToString(IPAddress inputAddr) { static char output[16]; // Static storage duration to return safely, 15 characters + null terminator snprintf(output, sizeof(output), "%d.%d.%d.%d", inputAddr[0], inputAddr[1], inputAddr[2], inputAddr[3]); @@ -16,7 +33,14 @@ const char *helperIpAddressToString(IPAddress inputAddr) { return output; } -int helperStringToLogLevel(const char *levelString) { +/** + * @brief Converts a string representation of a log level to its corresponding numeric value. + * + * @param levelString The string representation of the log level. + * + * @return The numeric value of the log level, or -1 if the input string is invalid. + */ +inline int helperStringToLogLevel(const char *levelString) { for (int i = 0; i < logLevelsSize; i++) { if (strcmp(logLevels[i].name, levelString) == 0) { logInfo(__func__, "Result: %d", logLevels[i].level); @@ -28,7 +52,18 @@ int helperStringToLogLevel(const char *levelString) { return -1; } -uint8_t helperPercentageToInteger(int percentage) { +/** + * @brief Converts percentage to an integer in the range of 0 to 255. + * + * This function takes a percentage value (0-100) and converts it to + * an integer value (0-255), scaling the percentage to fit the 8-bit + * range. If the input percentage is outside the 0-100 range, it will + * be clamped to ensure the return value stays within bounds. + * + * @param percentage The percentage to convert to an integer. Expected range is 0 to 100. + * @return The integer value of the percentage, scaled to 0-255. + */ +inline uint8_t helperPercentageToInteger(int percentage) { const char *logTag = __func__; if (percentage < 0) { diff --git a/src/Helpers.h b/src/Helpers.h index 30415bd..7dc318b 100644 --- a/src/Helpers.h +++ b/src/Helpers.h @@ -14,6 +14,7 @@ * @return `true` if the string starts with a protocol, `false` otherwise. */ bool helperCheckIfStringStartsWithProtocol(const char *input); +inline bool helperCheckIfStringStartsWithProtocol(const char *input); /** * @brief Converts IP Address of type IPAddress to a string. @@ -22,7 +23,7 @@ bool helperCheckIfStringStartsWithProtocol(const char *input); * * @return The string representation of the IP Address. */ -const char *helperIpAddressToString(IPAddress inputAddr); +inline const char *helperIpAddressToString(IPAddress inputAddr); /** * @brief Converts a string representation of a log level to its corresponding numeric value. @@ -31,7 +32,7 @@ const char *helperIpAddressToString(IPAddress inputAddr); * * @return The numeric value of the log level, or -1 if the input string is invalid. */ -int helperStringToLogLevel(const char *levelString); +inline int helperStringToLogLevel(const char *levelString); /** * @brief Converts percentage to an integer in the range of 0 to 255. @@ -44,6 +45,6 @@ int helperStringToLogLevel(const char *levelString); * @param percentage The percentage to convert to an integer. Expected range is 0 to 100. * @return The integer value of the percentage, scaled to 0-255. */ -uint8_t helperPercentageToInteger(int percentage); +inline uint8_t helperPercentageToInteger(int percentage); #endif // HELPERS_H_ From 414a72b8e4c83fd13bb8776cedaad1ba7a45c3ed Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 23:26:19 +0200 Subject: [PATCH 24/74] linting --- src/Helpers.cpp | 38 +------------------------------------- src/Helpers.h | 1 - 2 files changed, 1 insertion(+), 38 deletions(-) diff --git a/src/Helpers.cpp b/src/Helpers.cpp index afcbd97..58b72d7 100644 --- a/src/Helpers.cpp +++ b/src/Helpers.cpp @@ -1,29 +1,11 @@ #include "Helpers.h" - #include "Log.h" - -/** - * @brief Checks if a string starts with a protocol. - * - * This function checks if the input string starts with a protocol, such as `http` or `https`. - * - * @param input The string to check. - * - * @return `true` if the string starts with a protocol, `false` otherwise. - */ inline bool helperCheckIfStringStartsWithProtocol(const char *input) { // Check if input starts with "http" (includes "https") return strncmp(input, "http", 4) == 0; } -/** - * @brief Converts IP Address of type IPAddress to a string. - * - * @param inputAddr The IP Address to convert to a string. - * - * @return The string representation of the IP Address. - */ inline const char *helperIpAddressToString(IPAddress inputAddr) { static char output[16]; // Static storage duration to return safely, 15 characters + null terminator snprintf(output, sizeof(output), "%d.%d.%d.%d", inputAddr[0], inputAddr[1], inputAddr[2], inputAddr[3]); @@ -33,13 +15,6 @@ inline const char *helperIpAddressToString(IPAddress inputAddr) { return output; } -/** - * @brief Converts a string representation of a log level to its corresponding numeric value. - * - * @param levelString The string representation of the log level. - * - * @return The numeric value of the log level, or -1 if the input string is invalid. - */ inline int helperStringToLogLevel(const char *levelString) { for (int i = 0; i < logLevelsSize; i++) { if (strcmp(logLevels[i].name, levelString) == 0) { @@ -52,17 +27,6 @@ inline int helperStringToLogLevel(const char *levelString) { return -1; } -/** - * @brief Converts percentage to an integer in the range of 0 to 255. - * - * This function takes a percentage value (0-100) and converts it to - * an integer value (0-255), scaling the percentage to fit the 8-bit - * range. If the input percentage is outside the 0-100 range, it will - * be clamped to ensure the return value stays within bounds. - * - * @param percentage The percentage to convert to an integer. Expected range is 0 to 100. - * @return The integer value of the percentage, scaled to 0-255. - */ inline uint8_t helperPercentageToInteger(int percentage) { const char *logTag = __func__; @@ -76,4 +40,4 @@ inline uint8_t helperPercentageToInteger(int percentage) { // Calculate integer from percentage return (uint8_t)((percentage * 255) / 100); -} +} \ No newline at end of file diff --git a/src/Helpers.h b/src/Helpers.h index 7dc318b..baa7af5 100644 --- a/src/Helpers.h +++ b/src/Helpers.h @@ -13,7 +13,6 @@ * * @return `true` if the string starts with a protocol, `false` otherwise. */ -bool helperCheckIfStringStartsWithProtocol(const char *input); inline bool helperCheckIfStringStartsWithProtocol(const char *input); /** From 28cd5150a382bb264fc5a4a023651aca45ff2d64 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 23:32:12 +0200 Subject: [PATCH 25/74] linting --- src/Log.cpp | 58 ----------------------------------------------------- src/Log.h | 5 +---- 2 files changed, 1 insertion(+), 62 deletions(-) diff --git a/src/Log.cpp b/src/Log.cpp index b9b7110..ca628cc 100644 --- a/src/Log.cpp +++ b/src/Log.cpp @@ -23,15 +23,6 @@ const LogLevelMap logLevels[] = { const int logLevelsSize = sizeof(logLevels) / sizeof(LogLevelMap); -//////////////////////////////////////////////////////////////////////////////// - -/** - * @brief Converts a numeric log level to its corresponding string representation. - * - * @param level The numeric log level. - * - * @return The string representation of the log level. - */ const char *getLogLevelName(LogLevel level) { for (int i = 0; i < logLevelsSize; i++) { if (logLevels[i].level == level) { @@ -43,15 +34,6 @@ const char *getLogLevelName(LogLevel level) { return "UNKNOWN"; } -/** - * @brief Prints a log message to the serial output. - * - * @param level The level of the log message. - * @param glyph The emoji representing the log level. - * @param tag The tag identifying the log source. - * @param logMessage The log message format string. - * @param args Additional arguments to format the log message. - */ void logPrintSerialLine(LogLevel level, const char *glyph, const char *tag, const char *logMessage, va_list args) { // Check if serial connection is available and only continue if `level` is higher than globally set log level if (Serial) { @@ -68,13 +50,6 @@ void logPrintSerialLine(LogLevel level, const char *glyph, const char *tag, cons } } -/** - * @brief Logs a message at `DEBUG` level. - * - * @param logTag The tag identifying the log source. - * @param logMessage The log message format string. - * @param ... Additional arguments to format the log message. - */ void logDebug(const char *logTag, const char *logMessage, ...) { // Handle variable arguments: va_list args; @@ -86,13 +61,6 @@ void logDebug(const char *logTag, const char *logMessage, ...) { va_end(args); } -/** - * @brief Logs a message at `ERROR` level. - * - * @param logTag The tag identifying the log source. - * @param logMessage The log message format string. - * @param ... Additional arguments to format the log message. - */ void logError(const char *logTag, const char *logMessage, ...) { // Handle variable arguments: va_list args; @@ -104,13 +72,6 @@ void logError(const char *logTag, const char *logMessage, ...) { va_end(args); } -/** - * @brief Logs a message at `INFO` level. - * - * @param logTag The tag identifying the log source. - * @param logMessage The log message format string. - * @param ... Additional arguments to format the log message. - */ void logInfo(const char *logTag, const char *logMessage, ...) { // Handle variable arguments: va_list args; @@ -122,13 +83,6 @@ void logInfo(const char *logTag, const char *logMessage, ...) { va_end(args); } -/** - * @brief Logs a message at `WARN` level. - * - * @param logTag The tag identifying the log source. - * @param logMessage The log message format string. - * @param ... Additional arguments to format the log message. - */ void logWarning(const char *logTag, const char *logMessage, ...) { // Handle variable arguments: va_list args; @@ -140,13 +94,6 @@ void logWarning(const char *logTag, const char *logMessage, ...) { va_end(args); } -/** - * @brief Logs a message at `VERBOSE` level. - * - * @param logTag The tag identifying the log source. - * @param logMessage The log message format string. - * @param ... Additional arguments to format the log message. - */ void logVerbose(const char *logTag, const char *logMessage, ...) { // Handle variable arguments: va_list args; @@ -158,11 +105,6 @@ void logVerbose(const char *logTag, const char *logMessage, ...) { va_end(args); } -/** - * @brief Updates the global log level setting. - * - * @param level The new log level. - */ void logSetLevel(LogLevel level) { const char *logTag = __func__; diff --git a/src/Log.h b/src/Log.h index dcc2cb1..d4b456b 100644 --- a/src/Log.h +++ b/src/Log.h @@ -3,14 +3,11 @@ #include -#include -#include - //////////////////////////////////////////////////////////////////////////////// // CONFIGURATION // //////////////////////////////////////////////////////////////////////////////// -extern const size_t kLogLineBufferSize; +constexpr size_t kLogLineBufferSize = 256; // Example size, adjust as needed // Log levels enumeration typedef enum { LOG_NONE = 0, LOG_ERROR = 1, LOG_WARN = 2, LOG_INFO = 3, LOG_DEBUG = 4, LOG_VERBOSE = 5 } LogLevel; From 6f9ca3608e00286caba95b7871568b315940d077 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 23:34:29 +0200 Subject: [PATCH 26/74] linting --- src/Device.h | 1 - src/Display.h | 5 ++--- src/WifiClient.h | 1 - src/WireClient.h | 1 - 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Device.h b/src/Device.h index daa4d1e..606da1b 100644 --- a/src/Device.h +++ b/src/Device.h @@ -1,7 +1,6 @@ #ifndef DEVICE_H_ #define DEVICE_H_ -// Built-in and Third-Party libraries #include #include #include diff --git a/src/Display.h b/src/Display.h index fd818fd..4a76f3e 100644 --- a/src/Display.h +++ b/src/Display.h @@ -1,7 +1,6 @@ #ifndef DISPLAY_H_ #define DISPLAY_H_ -// Built-in and Third-Party libraries #include #include #include @@ -14,8 +13,8 @@ bool displayInit(); /** * @brief Updates the OLED display with the provided screen lines. * - * @param lines array of strings to be displayed on the screen. + * @param lines Array of strings to be displayed on the screen. */ void displayUpdate(const char *lines[4]); -#endif // DISPLAY_H_ +#endif // DISPLAY_H_ \ No newline at end of file diff --git a/src/WifiClient.h b/src/WifiClient.h index d1fc4da..3f6844d 100644 --- a/src/WifiClient.h +++ b/src/WifiClient.h @@ -1,7 +1,6 @@ #ifndef WIFICLIENT_H_ #define WIFICLIENT_H_ -// Built-in and Third-Party libraries #include #include diff --git a/src/WireClient.h b/src/WireClient.h index d0d75f2..95a79ab 100644 --- a/src/WireClient.h +++ b/src/WireClient.h @@ -1,7 +1,6 @@ #ifndef WIRECLIENT_H_ #define WIRECLIENT_H_ -// Built-in and Third-Party libraries #include /** From bbf49dc94a7304c8c88a1f8469a6519a7e93db64 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 23:40:02 +0200 Subject: [PATCH 27/74] linting --- src/Display.cpp | 30 +++++++++++------------------- src/Display.h | 2 +- src/Helpers.cpp | 3 ++- src/WifiClient.cpp | 1 + 4 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/Display.cpp b/src/Display.cpp index f85770c..c842289 100644 --- a/src/Display.cpp +++ b/src/Display.cpp @@ -7,29 +7,22 @@ //////////////////////////////////////////////////////////////////////////////// // Display height and width (in pixels) -const uint8_t displayHeight = 128; -const uint8_t displayWidth = 32; +constexpr uint8_t displayHeight = 128; +constexpr uint8_t displayWidth = 32; +// Display text color and size // See https://github.com/adafruit/Adafruit_SSD1306/blob/master/Adafruit_SSD1306.h for color overview -const uint16_t displayTextColor = SSD1306_WHITE; -const uint8_t displayTextSize = 1; +constexpr uint16_t displayTextColor = SSD1306_WHITE; +constexpr uint8_t displayTextSize = 1; // Display Reset Pin (or `-1` if shared with Arduino Reset Pin) -const int8_t displayResetPin = -1; +constexpr int8_t displayResetPin = -1; -// 128 x 32 display = `0x3C` -// 128 x 64 display = `0x3D` -const uint8_t displayAddress = 0x3C; - -// TODO(ksatirli) clean this up -// Default screen lines -char screenLine_0[50] = "Line 1"; -char screenLine_1[50] = "Line 2"; -char screenLine_2[50] = "Line 3"; -char screenLine_3[50] = "Line 4"; - -//////////////////////////////////////////////////////////////////////////////// +// Display address +// 128 x 32 display = `0x3C` +// 128 x 64 display = `0x3D` +constexpr uint8_t displayAddress = 0x3C; // Initialize display library Adafruit_SSD1306 display(displayWidth, displayHeight, &Wire, displayResetPin); @@ -37,7 +30,7 @@ Adafruit_SSD1306 display(displayWidth, displayHeight, &Wire, displayResetPin); bool displayInit() { const char *logTag = __func__; - // `SSD1306_SWITCHCAPVCC` = generate display voltage from 3.3V internal + // `SSD1306_SWITCHCAPVCC` = generate display voltage from 3.3V internally if (!display.begin(SSD1306_SWITCHCAPVCC, displayAddress)) { logError(logTag, "SSD1306 allocation failed"); @@ -50,7 +43,6 @@ bool displayInit() { display.setTextColor(displayTextColor); display.setTextSize(displayTextSize); - // Render image buffer on the display logDebug(logTag, "Rendering Image Buffer"); display.display(); diff --git a/src/Display.h b/src/Display.h index 4a76f3e..220e929 100644 --- a/src/Display.h +++ b/src/Display.h @@ -17,4 +17,4 @@ bool displayInit(); */ void displayUpdate(const char *lines[4]); -#endif // DISPLAY_H_ \ No newline at end of file +#endif // DISPLAY_H_ diff --git a/src/Helpers.cpp b/src/Helpers.cpp index 58b72d7..401aaa5 100644 --- a/src/Helpers.cpp +++ b/src/Helpers.cpp @@ -1,4 +1,5 @@ #include "Helpers.h" + #include "Log.h" inline bool helperCheckIfStringStartsWithProtocol(const char *input) { @@ -40,4 +41,4 @@ inline uint8_t helperPercentageToInteger(int percentage) { // Calculate integer from percentage return (uint8_t)((percentage * 255) / 100); -} \ No newline at end of file +} diff --git a/src/WifiClient.cpp b/src/WifiClient.cpp index 1cd2927..902bfbc 100644 --- a/src/WifiClient.cpp +++ b/src/WifiClient.cpp @@ -234,6 +234,7 @@ void wifiStartMdnsService(const char *hostname, const char *instance_name) { if (err) { // TODO(ksatirli): add `err` to log message logError(logTag, "Failed to initialize mDNS: %s", esp_err_to_name(err)); + return; } From 8d29881e892dc7cf6f6476a949648b83026e0181 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sat, 10 Aug 2024 23:46:13 +0200 Subject: [PATCH 28/74] linting --- src/Display.cpp | 1 - src/Log.h | 2 -- src/WifiClient.h | 2 +- src/WireClient.cpp | 4 ++-- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Display.cpp b/src/Display.cpp index c842289..a6e0411 100644 --- a/src/Display.cpp +++ b/src/Display.cpp @@ -12,7 +12,6 @@ constexpr uint8_t displayWidth = 32; // Display text color and size // See https://github.com/adafruit/Adafruit_SSD1306/blob/master/Adafruit_SSD1306.h for color overview - constexpr uint16_t displayTextColor = SSD1306_WHITE; constexpr uint8_t displayTextSize = 1; diff --git a/src/Log.h b/src/Log.h index d4b456b..82d12c2 100644 --- a/src/Log.h +++ b/src/Log.h @@ -7,8 +7,6 @@ // CONFIGURATION // //////////////////////////////////////////////////////////////////////////////// -constexpr size_t kLogLineBufferSize = 256; // Example size, adjust as needed - // Log levels enumeration typedef enum { LOG_NONE = 0, LOG_ERROR = 1, LOG_WARN = 2, LOG_INFO = 3, LOG_DEBUG = 4, LOG_VERBOSE = 5 } LogLevel; diff --git a/src/WifiClient.h b/src/WifiClient.h index 3f6844d..fa3f310 100644 --- a/src/WifiClient.h +++ b/src/WifiClient.h @@ -7,7 +7,7 @@ /** * @brief Generate Wi-Fi hostname. * - * @return nil if the hostname was generated successfully + * @return nullptr if the hostname was generated successfully */ char *wifiGenerateHostname(); diff --git a/src/WireClient.cpp b/src/WireClient.cpp index 8643f7c..b27c8a0 100644 --- a/src/WireClient.cpp +++ b/src/WireClient.cpp @@ -6,8 +6,8 @@ // CONFIGURATION // //////////////////////////////////////////////////////////////////////////////// -#define S_SCL 33 -#define S_SDA 32 +constexpr int S_SCL = 33; +constexpr int S_SDA = 32; //////////////////////////////////////////////////////////////////////////////// bool wireInit() { From 85808f1996dc17bc599bb41a355450d99ec93063 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sun, 11 Aug 2024 00:01:41 +0200 Subject: [PATCH 29/74] linting --- src/Device.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Device.cpp b/src/Device.cpp index 243d8a2..00bb1fa 100644 --- a/src/Device.cpp +++ b/src/Device.cpp @@ -1,5 +1,4 @@ #include "Device.h" - #include "Display.h" // TODO(ksatirli) re-enable when upstream warning is fixed From 1bcafc5afd6c213c0f6a2c08425acfcbfd94a310 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sun, 11 Aug 2024 00:22:37 +0200 Subject: [PATCH 30/74] linting --- src/Device.cpp | 1 + src/Filesystem.cpp | 28 ++++++++++++++++ src/Filesystem.h | 26 +++++++++++++++ src/HttpServer.cpp | 79 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 src/Filesystem.cpp create mode 100644 src/Filesystem.h create mode 100644 src/HttpServer.cpp diff --git a/src/Device.cpp b/src/Device.cpp index 00bb1fa..243d8a2 100644 --- a/src/Device.cpp +++ b/src/Device.cpp @@ -1,4 +1,5 @@ #include "Device.h" + #include "Display.h" // TODO(ksatirli) re-enable when upstream warning is fixed diff --git a/src/Filesystem.cpp b/src/Filesystem.cpp new file mode 100644 index 0000000..edf0875 --- /dev/null +++ b/src/Filesystem.cpp @@ -0,0 +1,28 @@ +#include "Filesystem.h" + +#include +#include "Log.h" + +bool filesystemInit() { + const char *logTag = __func__; + + if (!LittleFS.begin()) { + logError(logTag, "Unable to mount filesystem"); + return false; + } + + logInfo(logTag, "Successfully mounted filesystem"); + return true; +} + +File filesystemStreamFile(const String &filename, const char *mode) { + const char *logTag = __func__; + + File file = LittleFS.open(filename, mode); + + if (!file) { + logError(logTag, ("Failed to open file: " + filename).c_str()); + } + + return file; +} diff --git a/src/Filesystem.h b/src/Filesystem.h new file mode 100644 index 0000000..2eaa26a --- /dev/null +++ b/src/Filesystem.h @@ -0,0 +1,26 @@ +#ifndef FILESYSTEM_H_ +#define FILESYSTEM_H_ + +#include + +/** + * @brief Initialize the filesystem. + * + * This function initializes the LittleFS filesystem. + * + * @return True if the filesystem was successfully initialized, false otherwise. + */ +bool filesystemInit(); + +/** + * @brief Stream a file from the filesystem. + * + * This function opens a file from the filesystem in the specified mode. + * + * @param filename Name of the file to stream. + * @param mode Mode in which to open the file. + * @return A File object representing the opened file. + */ +File filesystemStreamFile(const String& filename, const char* mode); + +#endif // FILESYSTEM_H_ diff --git a/src/HttpServer.cpp b/src/HttpServer.cpp new file mode 100644 index 0000000..2bfabc2 --- /dev/null +++ b/src/HttpServer.cpp @@ -0,0 +1,79 @@ +#include "HttpServer.h" + +#include + +#include "Config.h" +#include "Filesystem.h" +#include "Log.h" + +//////////////////////////////////////////////////////////////////////////////// +// CONFIGURATION // +//////////////////////////////////////////////////////////////////////////////// + +// `7284` is `PATH` on a phone keypad +const uint16_t httpServerPort = 7284; +//////////////////////////////////////////////////////////////////////////////// + +// Declare a pointer for the HTTP server for dynamic allocation +WebServer *httpServer = nullptr; + +// Initialize HTTP server; this should be called in wifiConnect(), after WL_CONNECTED is reached +void httpServerInit() { + const char *logTag = __func__; + + if (httpServer) { + // Handle requests to root + httpServer->on("/", HTTP_GET, httpServerHandlerOnConnect); + + // Handle 404 not found errors + httpServer->onNotFound(httpServerHandlerNotFound); + + httpServer->begin(); + logInfo(logTag, "HTTP server started on port `%d`", httpServerPort); + } else { + logError(logTag, "HTTP server pointer is null, initialization failed"); + } +} + +bool httpServerStreamFile(WebServer *server, const char *filename, const char *contentType) { + bool httpServerStreamFile(WebServer * server, const char *filename, const char *contentType = "text/html") { + const char *logTag = __func__; + + File file = filesystemStreamFile(filename, "r"); + if (!file) { + logError(logTag, "Failed to open file `%s`", filename); + return false; + } + + server->streamFile(file, contentType); + file.close(); + + logInfo(logTag, "File streamed successfully `%s`", filename); + + return true; + } + + void httpServerHandleEvents() { + const char *logTag = __func__; + + if (httpServer) { + httpServer->handleClient(); + logInfo(logTag, "HTTP server handling client interactions"); + } else { + logError(logTag, "HTTP server not initialized"); + } + } + + void httpServerHandlerOnConnect() { + const char *logTag = __func__; + + if (!httpServerStreamFile(httpServer, "/index.html", "text/html")) { + httpServer->send(500, "text/plain", "Internal Server Error"); + } + } + + void httpServerHandlerNotFound() { + const char *logTag = __func__; + + httpServer->send(404, "text/plain", "404: Not Found"); + } From f013ac22e7db67a84dc5a75e24f2bc990c6489f4 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sun, 11 Aug 2024 00:37:59 +0200 Subject: [PATCH 31/74] work up for HTTP Server and LittleFS --- src/Filesystem.cpp | 1 + src/HttpServer.cpp | 59 ++++++++++++++++++----------------- src/HttpServer.h | 77 +++++++++++++++++++++++++++------------------- 3 files changed, 77 insertions(+), 60 deletions(-) diff --git a/src/Filesystem.cpp b/src/Filesystem.cpp index edf0875..ec325f5 100644 --- a/src/Filesystem.cpp +++ b/src/Filesystem.cpp @@ -1,6 +1,7 @@ #include "Filesystem.h" #include + #include "Log.h" bool filesystemInit() { diff --git a/src/HttpServer.cpp b/src/HttpServer.cpp index 2bfabc2..16ec3cb 100644 --- a/src/HttpServer.cpp +++ b/src/HttpServer.cpp @@ -36,44 +36,45 @@ void httpServerInit() { } bool httpServerStreamFile(WebServer *server, const char *filename, const char *contentType) { - bool httpServerStreamFile(WebServer * server, const char *filename, const char *contentType = "text/html") { - const char *logTag = __func__; - - File file = filesystemStreamFile(filename, "r"); - if (!file) { - logError(logTag, "Failed to open file `%s`", filename); - return false; - } + const char *logTag = __func__; - server->streamFile(file, contentType); - file.close(); + File file = filesystemStreamFile(filename, "r"); - logInfo(logTag, "File streamed successfully `%s`", filename); + if (!file) { + logError(logTag, "Failed to open file `%s`", filename); - return true; + return false; } - void httpServerHandleEvents() { - const char *logTag = __func__; + server->streamFile(file, contentType); + file.close(); - if (httpServer) { - httpServer->handleClient(); - logInfo(logTag, "HTTP server handling client interactions"); - } else { - logError(logTag, "HTTP server not initialized"); - } - } + logInfo(logTag, "File streamed successfully `%s`", filename); + + return true; +} - void httpServerHandlerOnConnect() { - const char *logTag = __func__; +void httpServerHandleEvents() { + const char *logTag = __func__; - if (!httpServerStreamFile(httpServer, "/index.html", "text/html")) { - httpServer->send(500, "text/plain", "Internal Server Error"); - } + if (httpServer) { + httpServer->handleClient(); + logInfo(logTag, "HTTP server handling client interactions"); + } else { + logError(logTag, "HTTP server not initialized"); } +} - void httpServerHandlerNotFound() { - const char *logTag = __func__; +void httpServerHandlerOnConnect() { + const char *logTag = __func__; - httpServer->send(404, "text/plain", "404: Not Found"); + if (!httpServerStreamFile(httpServer, "/index.html", "text/html")) { + httpServer->send(500, "text/plain", "Internal Server Error"); } +} + +void httpServerHandlerNotFound() { + const char *logTag = __func__; + + httpServer->send(404, "text/plain", "404: Not Found"); +} diff --git a/src/HttpServer.h b/src/HttpServer.h index f4862c1..9f5aef2 100644 --- a/src/HttpServer.h +++ b/src/HttpServer.h @@ -1,36 +1,51 @@ #ifndef HTTPSERVER_H_ #define HTTPSERVER_H_ -#include "./Assets.h" - -// Create AsyncWebServer object on port 80 -WebServer server(80); - -void httpServerHandleRoot() { - server.send(200, "text/html", assetWebserverIndex); // Send web page -} - -void httpServerController() { - server.on("/", httpServerHandleRoot); - - server.on("/js", []() { - String jsonCmdWebString = server.arg(0); - deserializeJson(jsonCmdReceive, jsonCmdWebString); - jsonCmdReceiveHandler(); - serializeJson(jsonInfoHttp, jsonFeedbackWeb); - server.send(200, "text/json", jsonFeedbackWeb); - jsonFeedbackWeb = ""; - jsonInfoHttp.clear(); - jsonCmdReceive.clear(); - }); - - // Start server - server.begin(); - Serial.println("Server Starts."); -} - -void httpServerInit() { - httpServerController(); -} +#include + +/** + * @brief Global pointer to the HTTP server instance. + */ +extern WebServer *httpServer; + +/** + * @brief Initialize and configure the HTTP server. + * + * This function sets up the HTTP server, registers request handlers, and starts the server. + */ +void httpServerInit(); + +/** + * @brief Stream a file over HTTP. + * + * This function streams a file to the client over HTTP. + * + * @param server Pointer to the WebServer instance. + * @param filename Name of the file to stream. + * @param contentType Content type of the file. + * @return True if the file was successfully streamed, false otherwise. + */ +bool httpServerStreamFile(WebServer *server, const char *filename, const char *contentType = "text/html"); + +/** + * @brief Begin processing incoming HTTP requests. + * + * This function handles incoming HTTP requests and processes them. + */ +void httpServerHandleEvents(); + +/** + * @brief Handle requests to the root ("/") path. + * + * This function handles HTTP GET requests to the root path. + */ +void httpServerHandlerOnConnect(); + +/** + * @brief Handle requests to undefined paths. + * + * This function handles HTTP requests to paths that are not defined. + */ +void httpServerHandlerNotFound(); #endif // HTTPSERVER_H_ From 31213e44fe97c31052733ec3916d8bf38a9402ec Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sun, 11 Aug 2024 01:29:48 +0200 Subject: [PATCH 32/74] expands HTTP Server --- src/Device.cpp | 15 ++++++++++----- src/Helpers.cpp | 3 ++- src/Helpers.h | 1 + src/HttpServer.cpp | 26 ++++++++++++++++++++------ src/HttpServer.h | 11 ++++++++++- 5 files changed, 43 insertions(+), 13 deletions(-) diff --git a/src/Device.cpp b/src/Device.cpp index 243d8a2..127ffeb 100644 --- a/src/Device.cpp +++ b/src/Device.cpp @@ -1,9 +1,8 @@ #include "Device.h" #include "Display.h" - -// TODO(ksatirli) re-enable when upstream warning is fixed -// #include "Insights.h" +#include "HttpServer.h" +// #include "Insights.h" // TODO(ksatirli) re-enable when upstream warning is fixed #include "Log.h" #include "WifiClient.h" #include "WireClient.h" @@ -19,7 +18,7 @@ char applicationCompilationString[32]; const char applicationInsightsKey[] = ""; // Toggle to sleep HTTP Server -const bool enableHttpServer = false; +const bool enableHttpServer = true; // Toggle to enable ESP Insights // See https://dashboard.insights.espressif.com/ @@ -98,6 +97,12 @@ bool deviceSetup() { return false; } + if (!httpServerInit()) { + logError(logTag, "Failed to initialize HTTP server"); + + return false; + } + if (!displayInit()) { logError(logTag, "Failed to initialize Display"); @@ -128,7 +133,7 @@ void deviceLoop() { if (enableHttpServer) { logDebug(logTag, "Handling HTTP Server events"); - // httpServerHandleEvents(); + httpServerHandleEvents(); } // Update display diff --git a/src/Helpers.cpp b/src/Helpers.cpp index 401aaa5..68922e2 100644 --- a/src/Helpers.cpp +++ b/src/Helpers.cpp @@ -8,7 +8,8 @@ inline bool helperCheckIfStringStartsWithProtocol(const char *input) { } inline const char *helperIpAddressToString(IPAddress inputAddr) { - static char output[16]; // Static storage duration to return safely, 15 characters + null terminator + // 15 characters + null terminator + static char output[16]; snprintf(output, sizeof(output), "%d.%d.%d.%d", inputAddr[0], inputAddr[1], inputAddr[2], inputAddr[3]); logInfo(__func__, "IP Address: %s", output); diff --git a/src/Helpers.h b/src/Helpers.h index baa7af5..5e187a0 100644 --- a/src/Helpers.h +++ b/src/Helpers.h @@ -21,6 +21,7 @@ inline bool helperCheckIfStringStartsWithProtocol(const char *input); * @param inputAddr The IP Address to convert to a string. * * @return The string representation of the IP Address. + * @return A string representation of the IPAddress. */ inline const char *helperIpAddressToString(IPAddress inputAddr); diff --git a/src/HttpServer.cpp b/src/HttpServer.cpp index 16ec3cb..350fec5 100644 --- a/src/HttpServer.cpp +++ b/src/HttpServer.cpp @@ -2,7 +2,6 @@ #include -#include "Config.h" #include "Filesystem.h" #include "Log.h" @@ -12,15 +11,30 @@ // `7284` is `PATH` on a phone keypad const uint16_t httpServerPort = 7284; -//////////////////////////////////////////////////////////////////////////////// // Declare a pointer for the HTTP server for dynamic allocation WebServer *httpServer = nullptr; +//////////////////////////////////////////////////////////////////////////////// -// Initialize HTTP server; this should be called in wifiConnect(), after WL_CONNECTED is reached -void httpServerInit() { +bool httpServerInit() { const char *logTag = __func__; + if (!httpServer) { + httpServer = new WebServer(httpServerPort); + logInfo(logTag, "HTTP server initialized on port `%d`", httpServerPort); + + return true; + } else { + logError(logTag, "HTTP server pointer is null, initialization failed"); + + return false; + } +} + +void httpServerMapRoutes() { + const char *logTag = __func__; + + // TODO(ksatirli) dynamically populate these entries from a config if (httpServer) { // Handle requests to root httpServer->on("/", HTTP_GET, httpServerHandlerOnConnect); @@ -29,9 +43,9 @@ void httpServerInit() { httpServer->onNotFound(httpServerHandlerNotFound); httpServer->begin(); - logInfo(logTag, "HTTP server started on port `%d`", httpServerPort); + logInfo(logTag, "HTTP server routes mapped and server started on port `%d`", httpServerPort); } else { - logError(logTag, "HTTP server pointer is null, initialization failed"); + logError(logTag, "HTTP server pointer is null, cannot map routes"); } } diff --git a/src/HttpServer.h b/src/HttpServer.h index 9f5aef2..7db7560 100644 --- a/src/HttpServer.h +++ b/src/HttpServer.h @@ -12,8 +12,17 @@ extern WebServer *httpServer; * @brief Initialize and configure the HTTP server. * * This function sets up the HTTP server, registers request handlers, and starts the server. + * + * @return True if the server was successfully initialized, false otherwise. + */ +bool httpServerInit(); + +/** + * @brief Map routes for the HTTP server. + * + * This function streams a file to the client over HTTP. */ -void httpServerInit(); +void httpServerMapRoutes(); /** * @brief Stream a file over HTTP. From 17bf0a4c9ca4ba53a4b132e5ab1b5e7f24826324 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sun, 11 Aug 2024 13:14:18 +0200 Subject: [PATCH 33/74] linting --- .clang-format | 9 +++++++++ src/Device.cpp | 3 +++ src/Display.cpp | 3 ++- src/WifiClient.cpp | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.clang-format b/.clang-format index 0725f40..53ebb66 100644 --- a/.clang-format +++ b/.clang-format @@ -4,6 +4,8 @@ # see https://google.github.io/styleguide/cppguide.html BasedOnStyle: Google +AccessModifierOffset: -2 + AlignAfterOpenBracket: true # see https://clang.llvm.org/docs/ClangFormatStyleOptions.html#alignarrayofstructures @@ -59,8 +61,15 @@ BraceWrapping: # see https://clang.llvm.org/docs/ClangFormatStyleOptions.html#columnlimit ColumnLimit: 999 +# see https://clang.llvm.org/docs/ClangFormatStyleOptions.html#emptylinebeforeaccessmodifier +EmptyLineBeforeAccessModifier: LogicalBlock + +# see https://clang.llvm.org/docs/ClangFormatStyleOptions.html#emptylineafteraccessmodifier +EmptyLineAfterAccessModifier: Always + # see https://clang.llvm.org/docs/ClangFormatStyleOptions.html#indentwidth IndentWidth: 4 +IndentAccessModifiers: false # see https://clang.llvm.org/docs/ClangFormatStyleOptions.html#language Language: Cpp diff --git a/src/Device.cpp b/src/Device.cpp index 127ffeb..d99b1e6 100644 --- a/src/Device.cpp +++ b/src/Device.cpp @@ -74,6 +74,9 @@ bool deviceSetup() { snprintf(applicationCompilationString, sizeof(applicationCompilationString), "%s at %s", __DATE__, __TIME__); // Print to serial monitor directly as loggers are not yet initialized + Serial.println(); + Serial.println('----------------------------------------------------------------'); + char initialLogMessage[64]; snprintf(initialLogMessage, sizeof(initialLogMessage), "[%s][🏁 START] Initializing device", logTag); Serial.println(initialLogMessage); diff --git a/src/Display.cpp b/src/Display.cpp index a6e0411..6ac227a 100644 --- a/src/Display.cpp +++ b/src/Display.cpp @@ -22,8 +22,9 @@ constexpr int8_t displayResetPin = -1; // 128 x 32 display = `0x3C` // 128 x 64 display = `0x3D` constexpr uint8_t displayAddress = 0x3C; +//////////////////////////////////////////////////////////////////////////////// -// Initialize display library +// Initialize Display Library Adafruit_SSD1306 display(displayWidth, displayHeight, &Wire, displayResetPin); bool displayInit() { diff --git a/src/WifiClient.cpp b/src/WifiClient.cpp index 902bfbc..05dacfe 100644 --- a/src/WifiClient.cpp +++ b/src/WifiClient.cpp @@ -227,7 +227,7 @@ void wifiScanNetworks() { void wifiStartMdnsService(const char *hostname, const char *instance_name) { const char *logTag = __func__; - // Initialize mDNS service + // Initialize mDNS Service logDebug(logTag, "Initializing mDNS service"); esp_err_t err = mdns_init(); From a04efbd8c9a1a3c1005a01c1e1e9bb6deb6ec946 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sun, 11 Aug 2024 13:14:32 +0200 Subject: [PATCH 34/74] moves HTML to external file --- assets/index.html | 1039 ++++++++++++++++++++++++++++++++++++++++++++ src/Assets.h | 1046 --------------------------------------------- 2 files changed, 1039 insertions(+), 1046 deletions(-) create mode 100644 assets/index.html delete mode 100644 src/Assets.h diff --git a/assets/index.html b/assets/index.html new file mode 100644 index 0000000..288eea0 --- /dev/null +++ b/assets/index.html @@ -0,0 +1,1039 @@ + + + + UGV01_BASE_WEB + + + + +
+
+
+

Control Panel

+
+
+
+
+
+
+ -1.01 + VOLTAGE +
+
+ -1.01 + RSSI +
+
+
+
+
+
+ -1.01 + ROLL +
+
+ -1.01 + PITCH +
+
+ -1.01 + TEMP +
+
+ -1.01 + PAN +
+
+ -1.01 + TILT +
+
+ -1.01 + SPD_R +
+
+
+
+
+
+ 192.168.10.67 + IP +
+
+ 44:17:93:EE:F8:F8 + MAC +
+
+
+
+
+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+
+
+ +
+
+
+
+
+ + + +
+
+
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+ + + +
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+

Feedback information

+ Json feedback information shows here. +
+
+
+ + +
+
+
+

EMERGENCY_STOP: {"T":0}

+ +
+
+

CMD_RESET_EMERGENCY: {"T":999}

+ +
+
+

SPEED_CTRL: {"T":1,"L":0.5,"R":0.5}

+ +
+
+

PID_SET: {"T":2,"P":200,"I":2500,"D":0,"L":255}

+ +
+
+

CMD_PWM_INPUT: {"T":11,"L":164,"R":164}

+ +
+
+

CMD_ROS_CTRL: {"T":13,"X":0.1,"Z":0.3}

+ +
+
+
+
+

OLED_SET: {"T":3,"lineNum":0,"Text":"putYourTextHere"}

+ +
+
+

OLED_DEFAULT: {"T":-3}

+ +
+
+
+
+

CMD_MODULE_TYPE: {"T":4,"cmd":0}

+ +
+
+

CMD_EOAT_TYPE: {"T":124,"mode":0}

+ +
+
+

CMD_CONFIG_EOAT: {"T":125,"pos":3,"ea":0,"eb":20}

+ +
+
+
+
+

CMD_GET_IMU_DATA: {"T":126}

+ +
+
+
+
+

CMD_BASE_FEEDBACK: {"T":130}

+ +
+
+

CMD_BASE_FEEDBACK_FLOW: {"T":131,"cmd":0}

+ +
+
+

FEEDBACK_FLOW_INTERVAL: {"T":142,"cmd":0}

+ +
+
+

CMD_UART_ECHO_MODE: {"T":143,"cmd":0}

+ +
+
+

CMD_HEART_BEAT_SET: {"T":136,"cmd":0}

+ +
+
+
+
+

CMD_LED_CTRL: {"T":132,"IO4":255,"IO5":255}

+ +
+
+

CMD_GIMBAL_CTRL_SIMPLE: {"T":133,"X":45,"Y":45,"SPD":0,"ACC":0}

+ +
+
+

CMD_GIMBAL_CTRL_MOVE: {"T":134,"X":45,"Y":45,"SX":300,"SY":300}

+ +
+
+

CMD_GIMBAL_CTRL_STOP: {"T":135}

+ +
+
+

CMD_GIMBAL_STEADY: {"T":137,"s":1,"y":0}

+ +
+
+

CMD_GIMBAL_USER_CTRL: {"T":141,"s":1,"y":0}

+ +
+
+
+
+

CMD_SET_SPD_RATE: {"T":138,"L":1,"R":1}

+ +
+
+

CMD_GET_SPD_RATE: {"T":139}

+ +
+
+

CMD_SAVE_SPD_RATE: {"T":140}

+ +
+
+
+
+

CMD_MISSION_CONTENT: {"T":221,"name":"mission_a"}

+ +
+
+

CMD_APPEND_STEP_JSON: {"T":222,"name":"mission_a","step":"{\"T\":137,\"s\":1,\"y\":0}"}

+ +
+
+
+
+

CMD_BROADCAST_FOLLOWER: {"T":300,"mode":1}

+ +
+
+

CMD_ESP_NOW_CONFIG: {"T":301,"mode":3}

+ +
+
+

CMD_GET_MAC_ADDRESS: {"T":302}

+ +
+
+

CMD_ESP_NOW_ADD_FOLLOWER: {"T":303,"mac":"FF:FF:FF:FF:FF:FF"}

+ +
+
+

CMD_ESP_NOW_REMOVE_FOLLOWER: {"T":304,"mac":"FF:FF:FF:FF:FF:FF"}

+ +
+
+

CMD_ESP_NOW_GROUP_CTRL: {"T":305,"dev":0,"b":0,"s":0,"e":1.57,"h":1.57,"cmd":0,"megs":"hello!"}

+ +
+
+

CMD_ESP_NOW_SINGLE: {"T":306,"mac":"FF:FF:FF:FF:FF:FF","dev":0,"b":0,"s":0,"e":1.57,"h":1.57,"cmd":0,"megs":"hello!"}

+ +
+
+
+
+

CMD_WIFI_ON_BOOT: {"T":401,"cmd":3}

+ +
+
+

CMD_SET_AP: {"T":402,"ssid":"UGV","password":"12345678"}

+ +
+
+

CMD_SET_STA: {"T":403,"ssid":"na","password":"ps"}

+ +
+
+

CMD_WIFI_APSTA: {"T":404,"ap_ssid":"UGV","ap_password":"12345678","sta_ssid":"na","sta_password":"ps"}

+ +
+
+

CMD_WIFI_INFO: {"T":405}

+ +
+
+

CMD_WIFI_CONFIG_CREATE_BY_STATUS: {"T":406}

+ +
+
+

CMD_WIFI_CONFIG_CREATE_BY_INPUT: {"T":407,"mode":3,"ap_ssid":"UGV","ap_password":"12345678","sta_ssid":"na","sta_password":"ps"}

+ +
+
+

CMD_WIFI_STOP: {"T":408}

+ +
+
+
+
+

CMD_SET_SERVO_ID: {"T":501,"raw":1,"new":11}

+ +
+
+

CMD_SET_MIDDLE: {"T":502,"id":11}

+ +
+
+

CMD_SET_SERVO_PID: {"T":503,"id":14,"p":16}

+ +
+
+
+
+

CMD_REBOOT: {"T":600}

+ +
+
+

CMD_FREE_FLASH_SPACE: {"T":601}

+ +
+
+

CMD_BOOT_MISSION_INFO: {"T":602}

+ +
+
+

CMD_RESET_BOOT_MISSION: {"T":603}

+ +
+
+

CMD_NVS_CLEAR: {"T":604}

+ +
+
+

CMD_INFO_PRINT: {"T":605,"cmd":1}

+ +
+
+
+
+

CMD_MM_TYPE_SET: {"T":900,"main":1,"module":0}

+ +
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/Assets.h b/src/Assets.h deleted file mode 100644 index 01b5278..0000000 --- a/src/Assets.h +++ /dev/null @@ -1,1046 +0,0 @@ -#ifndef ASSETS_H_ -#define ASSETS_H_ - -const char assetWebserverIndex[] PROGMEM = R"rawliteral( - - - - UGV01_BASE_WEB - - - - -
-
-
-

Control Panel

-
-
-
-
-
-
- -1.01 - VOLTAGE -
-
- -1.01 - RSSI -
-
-
-
-
-
- -1.01 - ROLL -
-
- -1.01 - PITCH -
-
- -1.01 - TEMP -
-
- -1.01 - PAN -
-
- -1.01 - TILT -
-
- -1.01 - SPD_R -
-
-
-
-
-
- 192.168.10.67 - IP -
-
- 44:17:93:EE:F8:F8 - MAC -
-
-
-
-
-
-
-
- - - -
-
- - - -
-
- - - -
-
-
-
-
-
- -
-
-
-
-
- - - -
-
-
-
-
- -
-
-
-
-
- - -
-
-
-
-
-
- - - -
-
-
-
-
- - - -
-
-
-
-
-
-
-
-

Feedback information

- Json feedback information shows here. -
-
-
- - -
-
-
-

EMERGENCY_STOP: {"T":0}

- -
-
-

CMD_RESET_EMERGENCY: {"T":999}

- -
-
-

SPEED_CTRL: {"T":1,"L":0.5,"R":0.5}

- -
-
-

PID_SET: {"T":2,"P":200,"I":2500,"D":0,"L":255}

- -
-
-

CMD_PWM_INPUT: {"T":11,"L":164,"R":164}

- -
-
-

CMD_ROS_CTRL: {"T":13,"X":0.1,"Z":0.3}

- -
-
-
-
-

OLED_SET: {"T":3,"lineNum":0,"Text":"putYourTextHere"}

- -
-
-

OLED_DEFAULT: {"T":-3}

- -
-
-
-
-

CMD_MODULE_TYPE: {"T":4,"cmd":0}

- -
-
-

CMD_EOAT_TYPE: {"T":124,"mode":0}

- -
-
-

CMD_CONFIG_EOAT: {"T":125,"pos":3,"ea":0,"eb":20}

- -
-
-
-
-

CMD_GET_IMU_DATA: {"T":126}

- -
-
-
-
-

CMD_BASE_FEEDBACK: {"T":130}

- -
-
-

CMD_BASE_FEEDBACK_FLOW: {"T":131,"cmd":0}

- -
-
-

FEEDBACK_FLOW_INTERVAL: {"T":142,"cmd":0}

- -
-
-

CMD_UART_ECHO_MODE: {"T":143,"cmd":0}

- -
-
-

CMD_HEART_BEAT_SET: {"T":136,"cmd":0}

- -
-
-
-
-

CMD_LED_CTRL: {"T":132,"IO4":255,"IO5":255}

- -
-
-

CMD_GIMBAL_CTRL_SIMPLE: {"T":133,"X":45,"Y":45,"SPD":0,"ACC":0}

- -
-
-

CMD_GIMBAL_CTRL_MOVE: {"T":134,"X":45,"Y":45,"SX":300,"SY":300}

- -
-
-

CMD_GIMBAL_CTRL_STOP: {"T":135}

- -
-
-

CMD_GIMBAL_STEADY: {"T":137,"s":1,"y":0}

- -
-
-

CMD_GIMBAL_USER_CTRL: {"T":141,"s":1,"y":0}

- -
-
-
-
-

CMD_SET_SPD_RATE: {"T":138,"L":1,"R":1}

- -
-
-

CMD_GET_SPD_RATE: {"T":139}

- -
-
-

CMD_SAVE_SPD_RATE: {"T":140}

- -
-
-
-
-

CMD_MISSION_CONTENT: {"T":221,"name":"mission_a"}

- -
-
-

CMD_APPEND_STEP_JSON: {"T":222,"name":"mission_a","step":"{\"T\":137,\"s\":1,\"y\":0}"}

- -
-
-
-
-

CMD_BROADCAST_FOLLOWER: {"T":300,"mode":1}

- -
-
-

CMD_ESP_NOW_CONFIG: {"T":301,"mode":3}

- -
-
-

CMD_GET_MAC_ADDRESS: {"T":302}

- -
-
-

CMD_ESP_NOW_ADD_FOLLOWER: {"T":303,"mac":"FF:FF:FF:FF:FF:FF"}

- -
-
-

CMD_ESP_NOW_REMOVE_FOLLOWER: {"T":304,"mac":"FF:FF:FF:FF:FF:FF"}

- -
-
-

CMD_ESP_NOW_GROUP_CTRL: {"T":305,"dev":0,"b":0,"s":0,"e":1.57,"h":1.57,"cmd":0,"megs":"hello!"}

- -
-
-

CMD_ESP_NOW_SINGLE: {"T":306,"mac":"FF:FF:FF:FF:FF:FF","dev":0,"b":0,"s":0,"e":1.57,"h":1.57,"cmd":0,"megs":"hello!"}

- -
-
-
-
-

CMD_WIFI_ON_BOOT: {"T":401,"cmd":3}

- -
-
-

CMD_SET_AP: {"T":402,"ssid":"UGV","password":"12345678"}

- -
-
-

CMD_SET_STA: {"T":403,"ssid":"na","password":"ps"}

- -
-
-

CMD_WIFI_APSTA: {"T":404,"ap_ssid":"UGV","ap_password":"12345678","sta_ssid":"na","sta_password":"ps"}

- -
-
-

CMD_WIFI_INFO: {"T":405}

- -
-
-

CMD_WIFI_CONFIG_CREATE_BY_STATUS: {"T":406}

- -
-
-

CMD_WIFI_CONFIG_CREATE_BY_INPUT: {"T":407,"mode":3,"ap_ssid":"UGV","ap_password":"12345678","sta_ssid":"na","sta_password":"ps"}

- -
-
-

CMD_WIFI_STOP: {"T":408}

- -
-
-
-
-

CMD_SET_SERVO_ID: {"T":501,"raw":1,"new":11}

- -
-
-

CMD_SET_MIDDLE: {"T":502,"id":11}

- -
-
-

CMD_SET_SERVO_PID: {"T":503,"id":14,"p":16}

- -
-
-
-
-

CMD_REBOOT: {"T":600}

- -
-
-

CMD_FREE_FLASH_SPACE: {"T":601}

- -
-
-

CMD_BOOT_MISSION_INFO: {"T":602}

- -
-
-

CMD_RESET_BOOT_MISSION: {"T":603}

- -
-
-

CMD_NVS_CLEAR: {"T":604}

- -
-
-

CMD_INFO_PRINT: {"T":605,"cmd":1}

- -
-
-
-
-

CMD_MM_TYPE_SET: {"T":900,"main":1,"module":0}

- -
-
-
-
-
- - - -)rawliteral"; - -#endif // ASSETS_H_ From 709971bdd2588a1b56934e9b1423381d4f8ed668 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sun, 11 Aug 2024 13:15:35 +0200 Subject: [PATCH 35/74] work-up for battery function --- src/Battery.cpp | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ src/Battery.h | 69 ++++++++++++++++++++++++------------------ 2 files changed, 120 insertions(+), 29 deletions(-) create mode 100644 src/Battery.cpp diff --git a/src/Battery.cpp b/src/Battery.cpp new file mode 100644 index 0000000..1554d30 --- /dev/null +++ b/src/Battery.cpp @@ -0,0 +1,80 @@ +#include "Battery.h" + +#include "Log.h" + +// Battery address +const uint8_t batteryAddress = 0x42; + +// Battery Bit Mode +// +// Resolution Time Mode +// 9 Bit 84 µs BIT_MODE_9 +// 10 Bit 148 µs BIT_MODE_10 +// 11 Bit 276 µs BIT_MODE_11 +// 12 Bit 532 µs BIT_MODE_12 (default) +const BitMode batteryBitMode = BIT_MODE_9; + +// Battery Power Gain (`PGain`) +// +// Gain Shunt max. current +// 40 mv 0.4 A PG_40 +// 80 mv 0.8 A PG_80 +// 160 mv 1.6 A PG_160 +// 320 mv 3.2 A PG_320 (default) +const PGain batteryPGain = PG_320; + +// Battery Bus Voltage Range +// +// 16 V = BRNG_16 +// 32 V = BRNG_32 (default) +const BRNG batteryBusVoltageRange = BRNG_16; + +// Battery Shunt Size +const float batteryShuntSize = 0.01; + +Battery::Battery() : ina219(batteryAddress) { +} + +bool Battery::setup() { + const char *logTag = __func__; + + if (!ina219.init()) { + logError(logTag, "Failed to initialize Battery"); + return false; + } + + logInfo(logTag, "Configure Battery"); + ina219.setADCMode(batteryBitMode); + ina219.setBusRange(batteryBusVoltageRange); + ina219.setPGain(batteryPGain); + ina219.setShuntSizeInOhms(batteryShuntSize); + + // Indicate that setup was successful + return true; +} + +void Battery::update() { + const char *logTag = __func__; + + logInfo(logTag, "Updating Battery Data"); + + data.shuntVoltage = ina219.getShuntVoltage_mV(); + data.busVoltage = ina219.getBusVoltage_V(); + data.current = ina219.getCurrent_mA(); + data.power = ina219.getBusPower(); + data.loadVoltage = data.busVoltage + (data.shuntVoltage / 1000); + data.ina219_overflow = ina219.getOverflow(); + + logDebug(logTag, "Battery Data:"); + logDebug(logTag, " Shunt: %s mV", data.shuntVoltage); + logDebug(logTag, " Bus: %s V", data.busVoltage); + logDebug(logTag, " Current: %s mV", data.current); + logDebug(logTag, " Power: %s V", data.power); + logDebug(logTag, " Overflow: %s", data.ina219_overflow); +} + +const BatteryData &Battery::getData() const { + return data; +} + +Battery battery; diff --git a/src/Battery.h b/src/Battery.h index f4175f2..f3cf18d 100644 --- a/src/Battery.h +++ b/src/Battery.h @@ -1,34 +1,45 @@ #ifndef BATTERY_H_ #define BATTERY_H_ -#define INA219_ADDRESS 0x42 -INA219_WE ina219 = INA219_WE(INA219_ADDRESS); - -float shuntVoltage_mV = 0.0; -float loadVoltage_V = 0.0; -float busVoltage_V = 0.0; -float current_mA = 0.0; -float power_mW = 0.0; -bool ina219_overflow = false; - -void ina219_init() { - if (!ina219.init()) { - Serial.println("INA219 not connected!"); - } - - ina219.setADCMode(BIT_MODE_9); - ina219.setPGain(PG_320); - ina219.setBusRange(BRNG_16); - ina219.setShuntSizeInOhms(0.01); // used in INA219. -} - -void inaDataUpdate() { - shuntVoltage_mV = ina219.getShuntVoltage_mV(); - busVoltage_V = ina219.getBusVoltage_V(); - current_mA = ina219.getCurrent_mA(); - power_mW = ina219.getBusPower(); - loadVoltage_V = busVoltage_V + (shuntVoltage_mV / 1000); - ina219_overflow = ina219.getOverflow(); -} +#include +#include +#include + +// Battery address +extern const uint8_t batteryAddress; + +// Battery Bit Mode +extern const BitMode batteryBitMode; + +// Battery Power Gain (`PGain`) +extern const PGain batteryPGain; + +// Battery Bus Voltage Range +extern const BRNG batteryBusVoltageRange; + +// Battery Shunt Size +extern const float batteryShuntSize; + +class BatteryData { + public: + float shuntVoltage = 0.0; // value in `mV` + float busVoltage = 0.0; // value in `V` + float current = 0.0; // value in `mV` + float power = 0.0; // value in `mW` + float loadVoltage = 0.0; // value in `V` + bool ina219_overflow = false; +}; + +class Battery { + public: + Battery(); + bool setup(); + void update(); + const BatteryData& getData() const; + + private: + INA219_WE ina219; + BatteryData data; +}; #endif // BATTERY_H_ From 1f3bedbb5244cab3bc4cd85d0366c017f5e0020b Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sun, 11 Aug 2024 23:30:42 +0200 Subject: [PATCH 36/74] aligns `clang-format` config with Google style --- .clang-format | 5 +++-- CMakeLists.txt | 28 +++++++++++----------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/.clang-format b/.clang-format index 53ebb66..af56060 100644 --- a/.clang-format +++ b/.clang-format @@ -4,7 +4,7 @@ # see https://google.github.io/styleguide/cppguide.html BasedOnStyle: Google -AccessModifierOffset: -2 +AccessModifierOffset: -1 AlignAfterOpenBracket: true @@ -23,6 +23,7 @@ AlignConsecutiveShortCaseStatements: AlignCaseColons: false AlignEscapedNewlines: Left + AlignOperands: true AlignTrailingComments: @@ -65,7 +66,7 @@ ColumnLimit: 999 EmptyLineBeforeAccessModifier: LogicalBlock # see https://clang.llvm.org/docs/ClangFormatStyleOptions.html#emptylineafteraccessmodifier -EmptyLineAfterAccessModifier: Always +EmptyLineAfterAccessModifier: Never # see https://clang.llvm.org/docs/ClangFormatStyleOptions.html#indentwidth IndentWidth: 4 diff --git a/CMakeLists.txt b/CMakeLists.txt index f125b4e..787b091 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,37 +9,31 @@ project( LANGUAGES CXX ) +# see https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_CLANG_TIDY.html +set(CMAKE_CXX_CLANG_TIDY clang-tidy -checks=-*,readability-*) + # see https://docs.espressif.com/projects/esp-idf/en/v3.30/esp32s3/api-guides/cplusplus.html -# and https://cmake.org/cmake/help/v3.30/command/set.html set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED True) # generate `compile_commands.json` for use with `clangd` -# see https://cmake.org/cmake/help/v3.30/command/set.html set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -# set common paths -# see https://cmake.org/cmake/help/v3.30/command/set.html # ⚠️ If this value is updated, it MUST be updated project-wide set(ARDUINO_BASE_PATH .arduino) -# see https://cmake.org/cmake/help/v3.30/command/set.html -set(ARDUINO_DATA_PATH ${ARDUINO_BASE_PATH}/data/packages) -set(ARDUINO_LIBS_PATH ${ARDUINO_BASE_PATH}/user/libraries) - -# set Arduino library version -# see https://cmake.org/cmake/help/v3.30/command/set.html +# set Arduino and ESP32 library versions +# ⚠️ If these values are updated, they MUST be updated project-wide set(ARDUINO_LIBRARY_VERSION 1.8.6) - -# set ESP32 library version -# ⚠️ If this value is updated, it MUST be updated project-wide -# see https://cmake.org/cmake/help/v3.30/command/set.html set(ESP32_LIBRARY_VERSION 2.0.17) # see https://cmake.org/cmake/help/v3.30/command/include_directories.html include_directories( - ${ARDUINO_LIBS_PATH} - ${ARDUINO_DATA_PATH}/arduino/hardware/avr/${ARDUINO_LIBRARY_VERSION}/libraries - ${ARDUINO_DATA_PATH}/esp32/hardware/esp32/${ESP32_LIBRARY_VERSION}/libraries + SYSTEM ${ARDUINO_BASE_PATH}/data/packages/arduino/hardware/avr/${ARDUINO_LIBRARY_VERSION}/cores/arduino + SYSTEM ${ARDUINO_BASE_PATH}/data/packages/arduino/hardware/avr/${ARDUINO_LIBRARY_VERSION}/libraries + SYSTEM ${ARDUINO_BASE_PATH}/data/packages/esp32/hardware/esp32/${ESP32_LIBRARY_VERSION}/cores/esp32 + SYSTEM ${ARDUINO_BASE_PATH}/user/libraries + SYSTEM ${ARDUINO_BASE_PATH}/data/packages/esp32/hardware/esp32/${ESP32_LIBRARY_VERSION}/libraries ) # include all source files in the `src` directory From 3dfd0b8603965c2d56ee321b91a40fdf9bec3446 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sun, 11 Aug 2024 23:35:54 +0200 Subject: [PATCH 37/74] linting --- src/Battery.cpp | 11 +++++------ src/Battery.h | 8 ++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Battery.cpp b/src/Battery.cpp index 1554d30..23ff258 100644 --- a/src/Battery.cpp +++ b/src/Battery.cpp @@ -1,5 +1,4 @@ #include "Battery.h" - #include "Log.h" // Battery address @@ -66,11 +65,11 @@ void Battery::update() { data.ina219_overflow = ina219.getOverflow(); logDebug(logTag, "Battery Data:"); - logDebug(logTag, " Shunt: %s mV", data.shuntVoltage); - logDebug(logTag, " Bus: %s V", data.busVoltage); - logDebug(logTag, " Current: %s mV", data.current); - logDebug(logTag, " Power: %s V", data.power); - logDebug(logTag, " Overflow: %s", data.ina219_overflow); + logDebug(logTag, " Shunt: %f mV", data.shuntVoltage); + logDebug(logTag, " Bus: %f V", data.busVoltage); + logDebug(logTag, " Current: %f mA", data.current); + logDebug(logTag, " Power: %f mW", data.power); + logDebug(logTag, " Overflow: %d", data.ina219_overflow); } const BatteryData &Battery::getData() const { diff --git a/src/Battery.h b/src/Battery.h index f3cf18d..74503cb 100644 --- a/src/Battery.h +++ b/src/Battery.h @@ -21,23 +21,23 @@ extern const BRNG batteryBusVoltageRange; extern const float batteryShuntSize; class BatteryData { - public: + public: float shuntVoltage = 0.0; // value in `mV` float busVoltage = 0.0; // value in `V` - float current = 0.0; // value in `mV` + float current = 0.0; // value in `mA` float power = 0.0; // value in `mW` float loadVoltage = 0.0; // value in `V` bool ina219_overflow = false; }; class Battery { - public: + public: Battery(); bool setup(); void update(); const BatteryData& getData() const; - private: + private: INA219_WE ina219; BatteryData data; }; From 6fffd99650439aae6cc89770dca6f03287d6030d Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Mon, 12 Aug 2024 13:09:40 +0200 Subject: [PATCH 38/74] adds library manager URLs --- src/Device.h | 2 +- src/Display.h | 2 +- src/Filesystem.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Device.h b/src/Device.h index 606da1b..5cc43fd 100644 --- a/src/Device.h +++ b/src/Device.h @@ -2,7 +2,7 @@ #define DEVICE_H_ #include -#include +#include // http://librarymanager/All/Other#ArduinoUniqueID #include /** diff --git a/src/Display.h b/src/Display.h index 220e929..6539f2f 100644 --- a/src/Display.h +++ b/src/Display.h @@ -1,7 +1,7 @@ #ifndef DISPLAY_H_ #define DISPLAY_H_ -#include +#include // http://librarymanager/All/Display#Adafruit_SSD1306 #include #include diff --git a/src/Filesystem.h b/src/Filesystem.h index 2eaa26a..cdee97c 100644 --- a/src/Filesystem.h +++ b/src/Filesystem.h @@ -1,7 +1,7 @@ #ifndef FILESYSTEM_H_ #define FILESYSTEM_H_ -#include +#include // http://librarymanager/All/Data%20Storage#LittleFS_esp32 /** * @brief Initialize the filesystem. From 982962cefa3dc80beb4a87cf5fe183545d0b6432 Mon Sep 17 00:00:00 2001 From: Kerim Satirli Date: Sun, 18 Aug 2024 22:21:02 +0100 Subject: [PATCH 39/74] HTML fixes --- assets/index.html | 50 +++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/assets/index.html b/assets/index.html index 288eea0..a588216 100644 --- a/assets/index.html +++ b/assets/index.html @@ -1,9 +1,9 @@ - + UGV01_BASE_WEB -