diff --git a/.github/workflows/test-EMULATOR.yml b/.github/workflows/test-EMULATOR.yml
index e16ca8712..12d46c9c6 100644
--- a/.github/workflows/test-EMULATOR.yml
+++ b/.github/workflows/test-EMULATOR.yml
@@ -2,9 +2,9 @@ name: Build OSW Emulator (Ubuntu)
on:
push:
- paths_ignore: '["**/*.md", "**/scripts/screen_capture/**"]'
+ paths-ignore: ["**/*.md", "**/scripts/screen_capture/**"]
pull_request:
- branches: [ master, develop ]
+ branches: [master, develop]
jobs:
check_skip:
@@ -15,8 +15,8 @@ jobs:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5.2.0
with:
- concurrent_skipping: 'same_content_newer'
- skip_after_successful_duplicate: 'true'
+ concurrent_skipping: "same_content_newer"
+ skip_after_successful_duplicate: "true"
build-EMULATOR:
runs-on: ubuntu-22.04
@@ -25,24 +25,36 @@ jobs:
strategy:
matrix:
build-configuration: [Debug, Release]
- steps:
- - name: Checkout repository and submodules
- # uses: actions/checkout@v3 # incompatible with git lfs cache bandwidth calcs (https://github.com/actions/checkout/issues/165)
- uses: nschloe/action-cached-lfs-checkout@v1.2.1
- with:
- submodules: recursive
- lfs: 'true'
- - name: Update packages
- run: sudo apt-get update
- - name: Install packages
- run: sudo apt-get -y install gcc g++ cmake libsdl2-dev libsdl2-image-dev python3 python3-pip
- - name: Install python packages
- run: pip3 install --user -r scripts/requirements.txt
- - name: Create build directory
- run: mkdir build
- - name: CMake ${{ matrix.build-configuration }}
- run: cd build && cmake -DCMAKE_BUILD_TYPE=${{ matrix.build-configuration }} ..
- - name: Make
- run: cd build && make -j $(nproc)
- - name: Test
- run: cd build && make test
+ steps:
+ # the following is incompatible with git lfs cache bandwidth calculations (https://github.com/actions/checkout/issues/165)
+ # -> we removed the following and replaced it with a cache-aware checkout
+ # - name: Checkout repository and submodules
+ # uses: actions/checkout@v3
+ # with:
+ # submodules: recursive
+ # lfs: 'true'
+ - name: Checkout repository and submodules
+ uses: nschloe/action-cached-lfs-checkout@v1.2.1
+ with:
+ submodules: recursive
+ - name: Update packages
+ run: sudo apt-get update
+ - name: Install packages
+ run: sudo apt-get -y install gcc g++ cmake libsdl2-dev libsdl2-image-dev python3 python3-pip
+ - name: Install python packages
+ run: pip3 install --user -r scripts/requirements.txt
+ - name: Create build directory
+ run: mkdir build
+ - name: CMake ${{ matrix.build-configuration }}
+ run: cd build && cmake -DCMAKE_BUILD_TYPE=${{ matrix.build-configuration }} ..
+ - name: Make
+ run: cd build && make -j $(nproc)
+ - name: Test
+ run: cd build && make test
+ - name: Upload test artifacts
+ if: failure()
+ uses: actions/upload-artifact@v4
+ with:
+ name: test-results
+ path: |
+ build/Testing
diff --git a/.github/workflows/test-FEATURE.yml b/.github/workflows/test-FEATURE.yml
index d6d96c740..73cc12d6c 100644
--- a/.github/workflows/test-FEATURE.yml
+++ b/.github/workflows/test-FEATURE.yml
@@ -2,9 +2,9 @@ name: Build OSW-OS (Ubuntu, additional features)
on:
push:
- paths_ignore: '["*.md", "**/scripts/screen_capture/**"]'
+ paths-ignore: ["*.md", "**/scripts/screen_capture/**"]
pull_request:
- branches: [ master, develop ]
+ branches: [master, develop]
jobs:
check_skip:
@@ -15,20 +15,18 @@ jobs:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5.2.0
with:
- concurrent_skipping: 'same_content_newer'
- skip_after_successful_duplicate: 'true'
+ concurrent_skipping: "same_content_newer"
+ skip_after_successful_duplicate: "true"
Find-feature:
runs-on: ubuntu-latest
needs: check_skip
if: ${{ needs.check_skip.outputs.should_skip != 'true' }}
- steps:
+ steps:
- name: Checkout repository and submodules
- # uses: actions/checkout@v3 # incompatible with git lfs cache bandwidth calcs (https://github.com/actions/checkout/issues/165)
uses: nschloe/action-cached-lfs-checkout@v1.2.1
with:
submodules: recursive
- lfs: 'true'
- id: get-flag
run: |
echo "feature=$(python3 .github/getWorkflowMatrix.py all_flags)" >> $GITHUB_OUTPUT
@@ -52,31 +50,29 @@ jobs:
model: ${{ fromJson(needs.Find-feature.outputs.default_model) }}
language: ${{ fromJson(needs.Find-feature.outputs.default_language) }}
steps:
- - name: Checkout repository and submodules
- # uses: actions/checkout@v3 # incompatible with git lfs cache bandwidth calcs (https://github.com/actions/checkout/issues/165)
- uses: nschloe/action-cached-lfs-checkout@v1.2.1
- with:
- submodules: recursive
- lfs: 'true'
- - name: Cache pip
- uses: actions/cache@v3
- with:
- path: ~/.cache/pip
- key: pip-${{ runner.os }}
- - name: Cache PlatformIO
- uses: actions/cache@v3
- with:
- path: ~/.platformio
- key: platformio-${{ runner.os }}
- - name: Install swig
- run: sudo apt-get update && sudo apt-get -y install swig
- - name: Set up Python
- uses: actions/setup-python@v4
- with:
- python-version: '3.10'
- - name: Install PlatformIO
- run: python -m pip install --upgrade pip && pip install --upgrade platformio
- - name: Rename config
- run: mv include/config.h.example include/config.h
- - name: Compile language ${{ matrix.language }} model ${{ matrix.model }} feature ${{ matrix.feature }}
- run: python3 .github/buildFirmware.py -l "${{ matrix.language }}" -m "${{ matrix.model }}" -f "${{ matrix.feature }}" -b debug
+ - name: Checkout repository and submodules
+ uses: nschloe/action-cached-lfs-checkout@v1.2.1
+ with:
+ submodules: recursive
+ - name: Cache pip
+ uses: actions/cache@v3
+ with:
+ path: ~/.cache/pip
+ key: pip-${{ runner.os }}
+ - name: Cache PlatformIO
+ uses: actions/cache@v3
+ with:
+ path: ~/.platformio
+ key: platformio-${{ runner.os }}
+ - name: Install swig
+ run: sudo apt-get update && sudo apt-get -y install swig
+ - name: Set up Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.10"
+ - name: Install PlatformIO
+ run: python -m pip install --upgrade pip && pip install --upgrade platformio
+ - name: Rename config
+ run: mv include/config.h.example include/config.h
+ - name: Compile language ${{ matrix.language }} model ${{ matrix.model }} feature ${{ matrix.feature }}
+ run: python3 .github/buildFirmware.py -l "${{ matrix.language }}" -m "${{ matrix.model }}" -f "${{ matrix.feature }}" -b debug
diff --git a/.github/workflows/test-OS.yml b/.github/workflows/test-OS.yml
index 20b2fbf26..1c26dff0c 100644
--- a/.github/workflows/test-OS.yml
+++ b/.github/workflows/test-OS.yml
@@ -4,18 +4,16 @@ on:
workflow_dispatch:
pull_request:
schedule:
- - cron: '0 0 * * *'
+ - cron: "0 0 * * *"
jobs:
Find-feature:
runs-on: ubuntu-latest
- steps:
+ steps:
- name: Checkout repository and submodules
- # uses: actions/checkout@v3 # incompatible with git lfs cache bandwidth calcs (https://github.com/actions/checkout/issues/165)
uses: nschloe/action-cached-lfs-checkout@v1.2.1
with:
submodules: recursive
- lfs: 'true'
- uses: dorny/paths-filter@v2.11.1
id: filter
with:
@@ -45,34 +43,32 @@ jobs:
model: ${{ fromJson(needs.Find-feature.outputs.get-models) }}
language: ${{ fromJson(needs.Find-feature.outputs.get-languages) }}
steps:
- - name: Checkout repository and submodules
- # uses: actions/checkout@v3 # incompatible with git lfs cache bandwidth calcs (https://github.com/actions/checkout/issues/165)
- uses: nschloe/action-cached-lfs-checkout@v1.2.1
- with:
- submodules: recursive
- lfs: 'true'
- - name: Cache pip
- uses: actions/cache@v3
- with:
- path: ~/.cache/pip
- key: pip-${{ runner.os }}
- - name: Cache PlatformIO
- uses: actions/cache@v3
- with:
- path: ~/.platformio
- key: platformio-${{ runner.os }}
- - name: Set up Python
- uses: actions/setup-python@v4
- with:
- python-version: '3.10'
+ - name: Checkout repository and submodules
+ uses: nschloe/action-cached-lfs-checkout@v1.2.1
+ with:
+ submodules: recursive
+ - name: Cache pip
+ uses: actions/cache@v3
+ with:
+ path: ~/.cache/pip
+ key: pip-${{ runner.os }}
+ - name: Cache PlatformIO
+ uses: actions/cache@v3
+ with:
+ path: ~/.platformio
+ key: platformio-${{ runner.os }}
+ - name: Set up Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.10"
- - name: Install PlatformIO
- shell: bash
- run: |
- apt update && apt -y install swig
- python -m pip install --upgrade pip
- pip install --upgrade platformio
- mv include/config.h.example include/config.h
+ - name: Install PlatformIO
+ shell: bash
+ run: |
+ apt update && apt -y install swig
+ python -m pip install --upgrade pip
+ pip install --upgrade platformio
+ mv include/config.h.example include/config.h
- - name: Compile language ${{ matrix.language }} model ${{ matrix.model }}
- run: python3 .github/buildFirmware.py -l "${{ matrix.language }}" -m "${{ matrix.model }}" -b debug
+ - name: Compile language ${{ matrix.language }} model ${{ matrix.model }}
+ run: python3 .github/buildFirmware.py -l "${{ matrix.language }}" -m "${{ matrix.model }}" -b debug
diff --git a/.github/workflows/test-OSW.yml b/.github/workflows/test-OSW.yml
index 3ba7758fd..3fbff9b88 100644
--- a/.github/workflows/test-OSW.yml
+++ b/.github/workflows/test-OSW.yml
@@ -3,9 +3,9 @@ name: Build OSW-OS (Ubuntu, all models)
on:
workflow_dispatch:
push:
- paths_ignore: '["*.md", "**/scripts/screen_capture/**"]'
+ paths-ignore: ["*.md", "**/scripts/screen_capture/**"]
pull_request:
- branches: [ master, develop ]
+ branches: [master, develop]
jobs:
check_skip:
@@ -16,20 +16,18 @@ jobs:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5.2.0
with:
- concurrent_skipping: 'same_content_newer'
- skip_after_successful_duplicate: 'true'
+ concurrent_skipping: "same_content_newer"
+ skip_after_successful_duplicate: "true"
Find-packages:
runs-on: ubuntu-latest
needs: check_skip
if: ${{ needs.check_skip.outputs.should_skip != 'true' }}
- steps:
+ steps:
- name: Checkout repository and submodules
- # uses: actions/checkout@v3 # incompatible with git lfs cache bandwidth calcs (https://github.com/actions/checkout/issues/165)
uses: nschloe/action-cached-lfs-checkout@v1.2.1
with:
submodules: recursive
- lfs: 'true'
- uses: dorny/paths-filter@v2.11.1
id: filter
with:
@@ -58,37 +56,35 @@ jobs:
model: ${{ fromJson(needs.Find-packages.outputs.models_matrix) }}
build-configuration: [debug, release]
steps:
- - name: Checkout repository and submodules
- # uses: actions/checkout@v3 # incompatible with git lfs cache bandwidth calcs (https://github.com/actions/checkout/issues/165)
- uses: nschloe/action-cached-lfs-checkout@v1.2.1
- with:
- submodules: recursive
- lfs: 'true'
- - name: Cache pip
- uses: actions/cache@v3
- with:
- path: ~/.cache/pip
- key: pip-${{ runner.os }}
- - name: Cache PlatformIO
- uses: actions/cache@v3
- with:
- path: ~/.platformio
- key: platformio-${{ runner.os }}
- - name: Install swig
- run: sudo apt-get update && sudo apt-get -y install swig
- - name: Set up Python
- uses: actions/setup-python@v4
- with:
- python-version: '3.10'
- - name: Install PlatformIO
- run: python -m pip install --upgrade pip && pip install --upgrade platformio
- - name: Rename config
- run: mv include/config.h.example include/config.h
- - name: Compile language ${{ matrix.language }} model ${{ matrix.model }}
- run: python3 .github/buildFirmware.py -l "${{ matrix.language }}" -m "${{ matrix.model }}" -b "${{ matrix.build-configuration }}"
- - name: Upload firmware artifacts
- uses: actions/upload-artifact@v3
- with:
- name: firmwares
- path: |
- *.bin
+ - name: Checkout repository and submodules
+ uses: nschloe/action-cached-lfs-checkout@v1.2.1
+ with:
+ submodules: recursive
+ - name: Cache pip
+ uses: actions/cache@v3
+ with:
+ path: ~/.cache/pip
+ key: pip-${{ runner.os }}
+ - name: Cache PlatformIO
+ uses: actions/cache@v3
+ with:
+ path: ~/.platformio
+ key: platformio-${{ runner.os }}
+ - name: Install swig
+ run: sudo apt-get update && sudo apt-get -y install swig
+ - name: Set up Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.10"
+ - name: Install PlatformIO
+ run: python -m pip install --upgrade pip && pip install --upgrade platformio
+ - name: Rename config
+ run: mv include/config.h.example include/config.h
+ - name: Compile language ${{ matrix.language }} model ${{ matrix.model }}
+ run: python3 .github/buildFirmware.py -l "${{ matrix.language }}" -m "${{ matrix.model }}" -b "${{ matrix.build-configuration }}"
+ - name: Upload firmware artifacts
+ uses: actions/upload-artifact@v3
+ with:
+ name: firmwares
+ path: |
+ *.bin
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6bd1d0d85..446455932 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -142,7 +142,8 @@ target_compile_definitions(emulator.run PUBLIC
# Comment these as you wish...
OSW_FEATURE_STATS_STEPS
OSW_FEATURE_WEATHER
- OSW_APPS_EXAMPLES=1
+ OSW_SERVICE_CONSOLE
+ OSW_APPS_EXAMPLES
GAME_SNAKE=1
GAME_BRICK_BREAKER=1
TOOL_FLASHLIGHT=1
diff --git a/README.md b/README.md
index 3c6e62857..cd93cfa18 100644
--- a/README.md
+++ b/README.md
@@ -51,7 +51,7 @@ If you want to compile for a specific model, you can use the `-e` flag with an `
## Hack it!
To get started, take a look into the examples in the `src/apps/examples` folder - or just into any other app. If you want to compile the examples or other (by default) excluded applications, take a look into the `main.cpp` file and add the respective flags to the `platformio.ini` file.
-## Debugging (CLI)
+## CLI
If you want to print out the log for debugging (also including decoded exception traces), use the following command:
@@ -59,6 +59,19 @@ If you want to print out the log for debugging (also including decoded exception
$ pio device monitor
```
+In this serial console you also have the ability (beside much more) to configure the watch - just type in `help` to get started:
+```
+OSW > help
+Available commands:
+ configure - enter configuration mode
+ help - show this help
+ hostname - show the device hostname
+ lock - lock the console
+ reboot - warm-start the device forcefully
+ time - show current UTC time
+ wipe - format NVS partition and reset configuration
+```
+
## Creating Screenshots of your Apps
@@ -98,6 +111,7 @@ $ cd scripts/screen_capture/
$ ./createScreenshot.sh
```
* The captured file can be found in the `screenshot/` folder inside the `open-smartwatch-os` directory.
+
## Troubleshooting
For more information on troubleshooting, see [Wiki](https://open-smartwatch.github.io/resources/firmware/#troubleshooting).
diff --git a/docs/firmware/osw_os.md b/docs/firmware/osw_os.md
index bef39b9bd..12bb66ab1 100644
--- a/docs/firmware/osw_os.md
+++ b/docs/firmware/osw_os.md
@@ -12,6 +12,15 @@ Flag | Description | Requirements
`GPS_EDITION` | Configure the build for use with GPS (including apps, api, sensors) | `PROGMEM_TILES`, `BOARD_HAS_PSRAM`
`GPS_EDITION_ROTATED` | Replacement for `GPS_EDITION` to work with flipped boards | -
+## Example Flags
+
+You want to know how to use some example code or see it in action? These flags enable vairous features that are not enabled by default - just search inside the source code for the flag to see how it works and what it does.
+
+Flag | Description | Requirements
+----------- | ----------- | -----------
+`OSW_SERVICE_EXAMPLE` | Enable the example code to demonstrate how to write on services. | -
+`OSW_APPS_EXAMPLES` | Enable the example code to demonstrate how to write own apps (v1/v2). | -
+
## Experimental Flags
These flags should be available on all models. Because they are experimental, they are not enabled by default any may won't work or even compile.
diff --git a/emulator/include/Serial.h b/emulator/include/Serial.h
index 694290f88..d4c610140 100644
--- a/emulator/include/Serial.h
+++ b/emulator/include/Serial.h
@@ -9,7 +9,7 @@
class Serial_t {
public:
- Serial_t() {};
+ Serial_t();
~Serial_t() {};
std::list buffer;
@@ -40,8 +40,12 @@ class Serial_t {
this->println();
}
+ int available();
+ int read();
+
void println();
private:
+ std::list inputBuffer;
int bauds = 0;
bool buffered = false;
bool addBufferNewline = true;
diff --git a/emulator/src/Serial.cpp b/emulator/src/Serial.cpp
index 25cc0b678..fae25e22d 100644
--- a/emulator/src/Serial.cpp
+++ b/emulator/src/Serial.cpp
@@ -1,8 +1,18 @@
#include "../include/Serial.h"
#include
+#include
+#include
+#include
+
Serial_t Serial;
+Serial_t::Serial_t() {
+ // put the stdin-stream into non-blocking mode to avoid hanging in case available() is called
+ int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
+ fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
+}
+
void Serial_t::setBuffered(bool buffered) {
this->buffered = buffered;
this->addBufferNewline = true;
@@ -26,4 +36,21 @@ void Serial_t::println() {
this->addBufferNewline = true;
else
std::cout << std::endl;
+}
+
+int Serial_t::available() {
+ char c;
+ if(::read(STDIN_FILENO, &c, 1) > 0) {
+ this->inputBuffer.push_back(c);
+ return true;
+ }
+ return false;
+}
+
+int Serial_t::read() {
+ if(this->inputBuffer.empty())
+ return -1;
+ char c = this->inputBuffer.front();
+ this->inputBuffer.pop_front();
+ return c;
}
\ No newline at end of file
diff --git a/emulator/src/tests/unitTests/logging.cpp b/emulator/src/tests/unitTests/logging.cpp
index b75378090..601d6abd9 100644
--- a/emulator/src/tests/unitTests/logging.cpp
+++ b/emulator/src/tests/unitTests/logging.cpp
@@ -10,7 +10,7 @@
* be bound to the stack-frame of its test - and destroyed upon leaving.
*/
-#define EXPECT_LASTLINE(expect) EXPECT_STREQ(expect, Serial.buffer.back().str().c_str())
+#define EXPECT_LASTLINE(expect) EXPECT_STREQ(expect, (Serial.buffer.size() ? Serial.buffer.back().str().c_str() : ""))
// Defines to use check log messages (all except debug!)
#ifndef NDEBUG
diff --git a/include/osw_config.h b/include/osw_config.h
index 43e97239e..603faaf18 100644
--- a/include/osw_config.h
+++ b/include/osw_config.h
@@ -47,6 +47,7 @@ class OswConfig {
String getCategoriesJson();
String getFieldJson(String id);
void setField(String id, String value);
+ void resetField(String id);
void notifyChange();
protected:
Preferences prefs; // for the config keys accessible
diff --git a/include/services/OswServiceTaskConsole.h b/include/services/OswServiceTaskConsole.h
new file mode 100644
index 000000000..dfb23eb19
--- /dev/null
+++ b/include/services/OswServiceTaskConsole.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "osw_service.h"
+
+class OswServiceTaskConsole : public OswServiceTask {
+ public:
+ OswServiceTaskConsole() {};
+ virtual void setup() override;
+ virtual void loop() override;
+ virtual void stop() override;
+ ~OswServiceTaskConsole() {};
+
+ private:
+ void newPrompt();
+ void showPrompt();
+ void runPrompt();
+ void showHelp();
+
+ std::string m_inputBuffer;
+ bool m_locked = false;
+ unsigned char m_lockCounter = 0;
+ bool m_configuring = false;
+};
\ No newline at end of file
diff --git a/include/services/OswServiceTaskExample.h b/include/services/OswServiceTaskExample.h
index 687f744c0..763d6a9f4 100644
--- a/include/services/OswServiceTaskExample.h
+++ b/include/services/OswServiceTaskExample.h
@@ -1,6 +1,5 @@
-#ifndef OSW_SERVICE_TASKEXAMPLE_H
-#define OSW_SERVICE_TASKEXAMPLE_H
-
+#pragma once
+#include
#include "osw_service.h"
class OswServiceTaskExample : public OswServiceTask {
@@ -14,5 +13,3 @@ class OswServiceTaskExample : public OswServiceTask {
private:
time_t printLimit = 0;
};
-
-#endif
\ No newline at end of file
diff --git a/platformio.ini b/platformio.ini
index 7ff9a6281..02960c9fe 100755
--- a/platformio.ini
+++ b/platformio.ini
@@ -44,6 +44,7 @@ build_unflags = -std=gnu++11 # The correct flag will be set by the cppflags pyth
build_flags =
-D OSW_TARGET_PLATFORM_HEADER='"platform/LIGHT_EDITION_V3_3.h"'
-D OSW_FEATURE_STATS_STEPS
+ -D OSW_SERVICE_CONSOLE
-D OSW_FEATURE_WIFI
build_type = debug
@@ -51,6 +52,7 @@ build_type = debug
build_flags =
-D OSW_TARGET_PLATFORM_HEADER='"platform/LIGHT_EDITION_V4_0.h"'
-D OSW_FEATURE_STATS_STEPS
+ -D OSW_SERVICE_CONSOLE
-D OSW_FEATURE_WIFI
-D OSW_FEATURE_WIFI_ONBOOT
build_type = debug
@@ -60,6 +62,7 @@ build_type = debug
build_flags =
-D OSW_TARGET_PLATFORM_HEADER='"platform/LIGHT_EDITION_V3_3.h"'
-D OSW_FEATURE_LUA
+ -D OSW_SERVICE_CONSOLE
-D OSW_FEATURE_WIFI
-D LUA_C89_NUMBERS ; Required by OSW_FEATURE_LUA
extra_scripts =
@@ -78,6 +81,7 @@ build_flags =
-D BOARD_HAS_PSRAM
-mfix-esp32-psram-cache-issue
-D OSW_FEATURE_STATS_STEPS
+ -D OSW_SERVICE_CONSOLE
-D OSW_FEATURE_WIFI
-D OSW_FEATURE_WIFI_APST
-D OSW_FEATURE_WIFI_ONBOOT
@@ -92,6 +96,7 @@ build_flags =
-D BOARD_HAS_PSRAM
-mfix-esp32-psram-cache-issue
-D OSW_FEATURE_STATS_STEPS
+ -D OSW_SERVICE_CONSOLE
-D OSW_FEATURE_WIFI
-D OSW_FEATURE_WIFI_APST
-D OSW_FEATURE_WIFI_ONBOOT
diff --git a/src/main.cpp b/src/main.cpp
index 661c111e1..553fd4ab7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -205,7 +205,7 @@ void loop() {
main_mainDrawer.registerApp("GPS", new OswAppV2Compat("osw.gps.mc", "Magnetometer Calibrate", gpsOswAppMC));
#endif
-#if OSW_APPS_EXAMPLES == 1
+#ifdef OSW_APPS_EXAMPLES
// For a short "How to write your own apps" see the examples below
main_mainDrawer.registerAppLazy(LANG_EXAMPLES); // only v2 apps support lazy loading (for now)
static OswAppExampleV1 exampleV1; // this is a static object, so it will be kept in memory until the device is reset - but it kind of defeats the purpose of lazy loading (static object = initialized on bootup, not on first use)
diff --git a/src/osw_config.cpp b/src/osw_config.cpp
index 4219ec2be..8125ed946 100644
--- a/src/osw_config.cpp
+++ b/src/osw_config.cpp
@@ -87,6 +87,7 @@ void OswConfig::reset(bool clearWholeNVS) {
bool res;
if(clearWholeNVS) {
this->prefs.end();
+ OSW_LOG_D("Formatting NVS partition...");
res = nvs_flash_erase() == ESP_OK;
assert(res);
res = nvs_flash_init() == ESP_OK;
@@ -155,6 +156,18 @@ void OswConfig::setField(String id, String value) {
this->notifyChange();
}
+void OswConfig::resetField(String id) {
+ unsigned char i = 0;
+ for (; i < oswConfigKeysCount; i++) {
+ OswConfigKey* key = oswConfigKeys[i];
+ if(String(key->id) == id) {
+ key->fromString(key->toDefaultString().c_str());
+ break;
+ }
+ }
+ this->notifyChange();
+}
+
void OswConfig::notifyChange() {
// Reload parts of the OS, which buffer values
// OswUI::getInstance()->resetTextColors(); // nope - this is done by the ui itself
diff --git a/src/services/OswServiceTaskConsole.cpp b/src/services/OswServiceTaskConsole.cpp
new file mode 100644
index 000000000..b77ced93d
--- /dev/null
+++ b/src/services/OswServiceTaskConsole.cpp
@@ -0,0 +1,187 @@
+#include "./services/OswServiceTaskConsole.h"
+#include "osw_hal.h"
+
+void OswServiceTaskConsole::setup() {
+ OswServiceTask::setup();
+ OSW_LOG_I("Console is now enabled.");
+#ifdef NDEBUG
+ this-> m_locked = true; // in release mode the console is locked by default
+#endif
+ this->newPrompt();
+}
+
+void OswServiceTaskConsole::loop() {
+ while(true) {
+ if(!Serial.available()) break;
+ char c = Serial.read();
+ switch (c) {
+ case 10: // LF
+ case 13: // CR
+ this->runPrompt();
+ this->newPrompt();
+ break;
+ case 8: // backspace
+ case 127: // delete
+ case 27: // escape
+ if(this->m_inputBuffer.length() > 0) {
+ this->m_inputBuffer.pop_back();
+ }
+ Serial.print(c);
+ break;
+ case 9: // tab
+ Serial.println(); // finish the prompt line
+ this->showHelp();
+ this->showPrompt();
+ break;
+ default:
+ if(32 <= c and c <= 126) { // printable characters
+ this->m_inputBuffer += c;
+ Serial.print(c); // echo the entered character back
+ } else {
+ Serial.print((char) 0x07); // bell
+ OSW_LOG_D("Unprocessable character (",(int) c, "): ", c);
+ }
+ }
+ }
+}
+
+void OswServiceTaskConsole::newPrompt() {
+ this->m_inputBuffer.clear();
+ if(this->m_locked) return;
+ this->showPrompt();
+}
+
+void OswServiceTaskConsole::showPrompt() {
+ if (this->m_configuring) {
+ Serial.print("OSW (configure) > ");
+ } else {
+ Serial.print("OSW > ");
+ }
+ if(!this->m_inputBuffer.empty()) {
+ Serial.print(this->m_inputBuffer.c_str());
+ }
+}
+
+void OswServiceTaskConsole::runPrompt() {
+ Serial.println(); // finish the prompt line
+ if(this->m_inputBuffer.empty()) return;
+ if(this->m_locked) {
+ Serial.println("Console is locked! Enter \"unlock\" to unlock.");
+ if(this->m_inputBuffer == "unlock") {
+ this->m_locked = false;
+ }
+ return;
+ }
+ // command convention: show only what was asked (preferably machine readable), only on error be verbose
+ bool processed = true;
+ if (this->m_configuring) {
+ if (this->m_inputBuffer == "clear") {
+ OswConfig::getInstance()->reset(false);
+ } else if (this->m_inputBuffer == "exit") {
+ this->m_configuring = false;
+ } else if (this->m_inputBuffer.find("get ") == 0 and this->m_inputBuffer.length() > 4) {
+ auto key = this->m_inputBuffer.substr(4);
+ for (auto i = 0; i < oswConfigKeysCount; i++) {
+ if(oswConfigKeys[i]->id == key) {
+ Serial.println(oswConfigKeys[i]->toString());
+ break;
+ }
+ }
+ } else if (this->m_inputBuffer.find("info ") == 0 and this->m_inputBuffer.length() > 5) {
+ auto key = this->m_inputBuffer.substr(5);
+ Serial.println(OswConfig::getInstance()->getFieldJson(key.c_str()));
+ } else if (this->m_inputBuffer == "help") {
+ this->showHelp();
+ } else if (this->m_inputBuffer == "list") {
+ for (auto i = 0; i < oswConfigKeysCount; i++) {
+ Serial.println(oswConfigKeys[i]->id);
+ }
+ } else if (this->m_inputBuffer.find("reset ") == 0 and this->m_inputBuffer.length() > 7) {
+ auto key = this->m_inputBuffer.substr(7);
+ OswConfig::getInstance()->enableWrite();
+ OswConfig::getInstance()->resetField(key.c_str());
+ OswConfig::getInstance()->disableWrite();
+ } else if (this->m_inputBuffer.find("set ") == 0 and this->m_inputBuffer.length() > 5) {
+ auto key = this->m_inputBuffer.substr(4); // " "
+ auto space = key.find(" ", 0);
+ if (space == std::string::npos) {
+ Serial.println("Invalid command.");
+ return;
+ }
+ auto value = key.substr(space + 1); // ""
+ key = key.substr(0, space); // ""
+ OswConfig::getInstance()->enableWrite();
+ OswConfig::getInstance()->setField(key.c_str(), value.c_str());
+ OswConfig::getInstance()->disableWrite();
+ } else {
+ processed = false;
+ }
+ } else {
+ if (this->m_inputBuffer == "configure") {
+ this->m_configuring = true;
+ } else if (this->m_inputBuffer == "help") {
+ this->showHelp();
+#ifdef OSW_FEATURE_WIFI
+ } else if (this->m_inputBuffer == "hostname") {
+ Serial.println(OswConfigAllKeys::hostname.get());
+#endif
+ } else if (this->m_inputBuffer == "lock") {
+ this->m_locked = true;
+#ifndef OSW_EMULATOR
+ } else if (this->m_inputBuffer == "reboot") {
+ // this does not work in the emulator as it is running under an own thread, of which the shutdown-exception is not captured - populating here and crashing
+ ESP.restart();
+#endif
+ } else if (this->m_inputBuffer == "time") {
+ Serial.println(OswHal::getInstance()->getUTCTime());
+ } else if (this->m_inputBuffer == "wipe") {
+ OswConfig::getInstance()->reset(true);
+ } else {
+ processed = false;
+ }
+ }
+ // show help if the command was not processed
+ if (!processed) {
+ Serial.println("Unknown command.");
+ Serial.println();
+ this->showHelp();
+ this->m_lockCounter++;
+ }
+ // in case of garbage input, lock the console after 16 attempts
+ if (this->m_lockCounter > 16) {
+ this->m_locked = true;
+ this->m_lockCounter = 0;
+ }
+}
+
+void OswServiceTaskConsole::showHelp() {
+ Serial.println("Available commands:");
+ // let's try to be civil and show the commands in alphabetical order
+ if (this->m_configuring) {
+ Serial.println(" clear - reset all keys to default values");
+ Serial.println(" exit - leave configuration mode");
+ Serial.println(" get - get a value for a key");
+ Serial.println(" help - show this help");
+ Serial.println(" info - show more information about a key");
+ Serial.println(" list - show all keys");
+ Serial.println(" reset - reset a key to default value");
+ Serial.println(" set - set a value for a key (value is everything until the end of the line)");
+ } else {
+ Serial.println(" configure - enter configuration mode");
+ Serial.println(" help - show this help");
+#ifdef OSW_FEATURE_WIFI
+ Serial.println(" hostname - show the device hostname");
+#endif
+ Serial.println(" lock - lock the console");
+#ifndef OSW_EMULATOR
+ Serial.println(" reboot - warm-start the device forcefully");
+#endif
+ Serial.println(" time - show current UTC time");
+ Serial.println(" wipe - format NVS partition and reset configuration");
+ }
+}
+
+void OswServiceTaskConsole::stop() {
+ OSW_LOG_I("Console is now disabled.");
+ OswServiceTask::stop();
+}
\ No newline at end of file
diff --git a/src/services/OswServiceTaskExample.cpp b/src/services/OswServiceTaskExample.cpp
index fa0084361..252f7f7e4 100644
--- a/src/services/OswServiceTaskExample.cpp
+++ b/src/services/OswServiceTaskExample.cpp
@@ -1,6 +1,5 @@
-#include "./services/OswServiceTaskExample.h"
#include "osw_hal.h"
-#include
+#include "./services/OswServiceTaskExample.h"
void OswServiceTaskExample::setup() {
OswServiceTask::setup();
@@ -16,6 +15,6 @@ void OswServiceTaskExample::loop() {
}
void OswServiceTaskExample::stop() {
- OswServiceTask::stop();
OSW_LOG_I(__FUNCTION__, "()");
-}
\ No newline at end of file
+ OswServiceTask::stop();
+}
diff --git a/src/services/OswServiceTaskWebserver.cpp b/src/services/OswServiceTaskWebserver.cpp
index 9a03ba758..4311d5e59 100644
--- a/src/services/OswServiceTaskWebserver.cpp
+++ b/src/services/OswServiceTaskWebserver.cpp
@@ -297,8 +297,8 @@ void OswServiceTaskWebserver::loop() {
}
void OswServiceTaskWebserver::stop() {
- OswServiceTask::stop();
this->disableWebserver(); //Make sure the webserver is also stopped
+ OswServiceTask::stop();
}
void OswServiceTaskWebserver::enableWebserver() {
diff --git a/src/services/OswServiceTaskWiFi.cpp b/src/services/OswServiceTaskWiFi.cpp
index 867092872..3c15dd6e1 100644
--- a/src/services/OswServiceTaskWiFi.cpp
+++ b/src/services/OswServiceTaskWiFi.cpp
@@ -137,8 +137,8 @@ void OswServiceTaskWiFi::selectCredentials() {
}
void OswServiceTaskWiFi::stop() {
- OswServiceTask::stop();
this->disableWiFi();
+ OswServiceTask::stop();
}
/**
diff --git a/src/services/OswServiceTasks.cpp b/src/services/OswServiceTasks.cpp
index 45aa19ff6..8913eeec1 100644
--- a/src/services/OswServiceTasks.cpp
+++ b/src/services/OswServiceTasks.cpp
@@ -5,6 +5,7 @@
#include "services/OswServiceTaskGPS.h"
#include "services/OswServiceTaskMemMonitor.h"
#include "services/OswServiceTaskNotifier.h"
+#include "services/OswServiceTaskConsole.h"
#ifdef OSW_FEATURE_WIFI
#include "services/OswServiceTaskWiFi.h"
#include "services/OswServiceTaskWebserver.h"
@@ -12,6 +13,9 @@
#include "osw_util.h"
namespace OswServiceAllTasks {
+#ifdef OSW_SERVICE_EXAMPLE
+OswServiceTaskExample example;
+#endif
// OswServiceTaskExample example;
#if SERVICE_BLE_COMPANION == 1
OswServiceTaskBLECompanion bleCompanion;
@@ -30,6 +34,9 @@ OswServiceTaskNotifier notifier;
#ifndef OSW_EMULATOR
OswServiceTaskMemMonitor memory;
#endif
+#ifdef OSW_SERVICE_CONSOLE
+OswServiceTaskConsole console;
+#endif
} // namespace OswServiceAllTasks
OswServiceTask* oswServiceTasks[] = {
@@ -40,13 +47,18 @@ OswServiceTask* oswServiceTasks[] = {
& OswServiceAllTasks::gps,
#endif
-//&OswServiceAllTasks::example,
+#ifdef OSW_SERVICE_EXAMPLE
+ & OswServiceAllTasks::example,
+#endif
#ifdef OSW_FEATURE_WIFI
& OswServiceAllTasks::wifi, &OswServiceAllTasks::webserver,
#endif
#if OSW_SERVICE_NOTIFIER == 1
& OswServiceAllTasks::notifier,
#endif
+#ifdef OSW_SERVICE_CONSOLE
+ & OswServiceAllTasks::console,
+#endif
#ifndef OSW_EMULATOR
#ifndef NDEBUG
& OswServiceAllTasks::memory