diff --git a/.github/workflows/build-clang-doxy.yml b/.github/workflows/build-clang-doxy.yml index e0ea16fe4..4d00deb85 100644 --- a/.github/workflows/build-clang-doxy.yml +++ b/.github/workflows/build-clang-doxy.yml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Brent Rubell for Adafruit Industries, 2023 +# SPDX-FileCopyrightText: Brent Rubell for Adafruit Industries, 2023-2025 # # SPDX-License-Identifier: MIT name: WipperSnapper Build CI @@ -6,6 +6,8 @@ name: WipperSnapper Build CI on: workflow_dispatch: pull_request: + branches-ignore: + - 'offline-mode' workflow_call: secrets: GH_REPO_TOKEN: diff --git a/.github/workflows/release-offline.yml b/.github/workflows/release-offline.yml index 189615a6f..b429ddddc 100644 --- a/.github/workflows/release-offline.yml +++ b/.github/workflows/release-offline.yml @@ -6,6 +6,7 @@ on: push: branches: - offline-mode + - offline-mode-* release: types: [published] branches: @@ -165,8 +166,8 @@ jobs: tree - name: Rename build artifacts to reflect the platform name run: | - mv examples/*/build/*/Wippersnapper_demo.ino.uf2 wippersnapper.${{ matrix.arduino-platform }}.${{ env.WS_VERSION }}.uf2 - mv examples/*/build/*/Wippersnapper_demo.ino.bin wippersnapper.${{ matrix.arduino-platform }}.${{ env.WS_VERSION }}.bin + mv examples/*/build/*/Wippersnapper_demo_offline_netiface.ino.uf2 wippersnapper.${{ matrix.arduino-platform }}.${{ env.WS_VERSION }}.uf2 + mv examples/*/build/*/Wippersnapper_demo_offline_netiface.ino.bin wippersnapper.${{ matrix.arduino-platform }}.${{ env.WS_VERSION }}.bin - name: upload build artifacts uses: actions/upload-artifact@v4 with: @@ -183,10 +184,10 @@ jobs: fail-fast: false matrix: arduino-platform: ["pico_rp2040_tinyusb", - "pico_rp2350_tinyusb", - "feather_rp2040_adalogger_tinyusb", - "metro_rp2350_tinyusb" - ] + "pico_rp2350_tinyusb", + "feather_rp2040_adalogger_tinyusb", + "metro_rp2350_tinyusb" + ] steps: - uses: actions/setup-python@v5 with: @@ -243,7 +244,7 @@ jobs: run: python3 ci/build_platform.py ${{ matrix.arduino-platform }} --build_timeout 48000 - name: Rename build artifacts to reflect the platform name run: | - mv examples/*/build/*/Wippersnapper_demo_offline.ino.uf2 wippersnapper.${{ matrix.arduino-platform }}.${{ env.WS_VERSION }}.uf2 + mv examples/*/build/*/Wippersnapper_demo_offline_nonetiface.ino.uf2 wippersnapper.${{ matrix.arduino-platform }}.${{ env.WS_VERSION }}.uf2 - name: upload build artifacts uses: actions/upload-artifact@v4 with: diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32.test.skip diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32_v2.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32_v2.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32_v2.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32_v2.test.skip diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32_v2_debug.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32_v2_debug.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32_v2_debug.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32_v2_debug.test.skip diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32s2.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32s2.generate similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32s2.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32s2.generate diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32s2_debug.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32s2_debug.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32s2_debug.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32s2_debug.test.skip diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32s2_reverse_tft.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32s2_reverse_tft.generate similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32s2_reverse_tft.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32s2_reverse_tft.generate diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32s2_tft.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32s2_tft.generate similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32s2_tft.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32s2_tft.generate diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32s2_tft_debug.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32s2_tft_debug.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32s2_tft_debug.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32s2_tft_debug.skip diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32s2_tft_debug.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32s2_tft_debug.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32s2_tft_debug.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32s2_tft_debug.test.skip diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32s3.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32s3.generate similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32s3.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32s3.generate diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32s3_4mbflash_2mbpsram.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32s3_4mbflash_2mbpsram.generate similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32s3_4mbflash_2mbpsram.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32s3_4mbflash_2mbpsram.generate diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32s3_4mbflash_2mbpsram_debug.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32s3_4mbflash_2mbpsram_debug.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32s3_4mbflash_2mbpsram_debug.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32s3_4mbflash_2mbpsram_debug.test.skip diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32s3_debug.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32s3_debug.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32s3_debug.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32s3_debug.test.skip diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32s3_reverse_tft.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32s3_reverse_tft.generate similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32s3_reverse_tft.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32s3_reverse_tft.generate diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32s3_tft.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32s3_tft.generate similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32s3_tft.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32s3_tft.generate diff --git a/examples/Wippersnapper_demo_offline/.feather_esp32s3_tft_debug.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp32s3_tft_debug.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp32s3_tft_debug.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp32s3_tft_debug.test.skip diff --git a/examples/Wippersnapper_demo_offline/.feather_esp8266.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_esp8266.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_esp8266.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_esp8266.test.skip diff --git a/examples/Wippersnapper_demo_offline/.feather_rp2040_adalogger_tinyusb.generate b/examples/Wippersnapper_demo_offline_netiface/.feather_rp2040_adalogger_tinyusb.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_rp2040_adalogger_tinyusb.generate rename to examples/Wippersnapper_demo_offline_netiface/.feather_rp2040_adalogger_tinyusb.test.skip diff --git a/examples/Wippersnapper_demo_offline/.feather_s2_tinyusb.test.skip b/examples/Wippersnapper_demo_offline_netiface/.feather_s2_tinyusb.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.feather_s2_tinyusb.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.feather_s2_tinyusb.test.skip diff --git a/examples/Wippersnapper_demo_offline/.funhouse.test.skip b/examples/Wippersnapper_demo_offline_netiface/.funhouse.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.funhouse.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.funhouse.test.skip diff --git a/examples/Wippersnapper_demo_offline/.funhouse_noota.test.skip b/examples/Wippersnapper_demo_offline_netiface/.funhouse_noota.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.funhouse_noota.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.funhouse_noota.test.skip diff --git a/examples/Wippersnapper_demo_offline/.itsybitsy_esp32.test.skip b/examples/Wippersnapper_demo_offline_netiface/.itsybitsy_esp32.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.itsybitsy_esp32.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.itsybitsy_esp32.test.skip diff --git a/examples/Wippersnapper_demo_offline/.magtag.test.skip b/examples/Wippersnapper_demo_offline_netiface/.magtag.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.magtag.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.magtag.test.skip diff --git a/examples/Wippersnapper_demo_offline/.metro_esp32s3.test.skip b/examples/Wippersnapper_demo_offline_netiface/.metro_esp32s3.generate similarity index 100% rename from examples/Wippersnapper_demo_offline/.metro_esp32s3.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.metro_esp32s3.generate diff --git a/examples/Wippersnapper_demo_offline/.metro_esp32s3_debug.test.skip b/examples/Wippersnapper_demo_offline_netiface/.metro_esp32s3_debug.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.metro_esp32s3_debug.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.metro_esp32s3_debug.test.skip diff --git a/examples/Wippersnapper_demo_offline/.metro_m4_airliftlite_tinyusb.test.skip b/examples/Wippersnapper_demo_offline_netiface/.metro_m4_airliftlite_tinyusb.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.metro_m4_airliftlite_tinyusb.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.metro_m4_airliftlite_tinyusb.test.skip diff --git a/examples/Wippersnapper_demo_offline/.metro_rp2350_tinyusb.generate b/examples/Wippersnapper_demo_offline_netiface/.metro_rp2350_tinyusb.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.metro_rp2350_tinyusb.generate rename to examples/Wippersnapper_demo_offline_netiface/.metro_rp2350_tinyusb.test.skip diff --git a/examples/Wippersnapper_demo_offline/.metroesp32s2.test.skip b/examples/Wippersnapper_demo_offline_netiface/.metroesp32s2.generate similarity index 100% rename from examples/Wippersnapper_demo_offline/.metroesp32s2.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.metroesp32s2.generate diff --git a/examples/Wippersnapper_demo_offline/.metroesp32s2_debug.test.skip b/examples/Wippersnapper_demo_offline_netiface/.metroesp32s2_debug.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.metroesp32s2_debug.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.metroesp32s2_debug.test.skip diff --git a/examples/Wippersnapper_demo_offline/.pico_rp2040_tinyusb.generate b/examples/Wippersnapper_demo_offline_netiface/.pico_rp2040_tinyusb.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.pico_rp2040_tinyusb.generate rename to examples/Wippersnapper_demo_offline_netiface/.pico_rp2040_tinyusb.test.skip diff --git a/examples/Wippersnapper_demo_offline/.pico_rp2350_tinyusb.generate b/examples/Wippersnapper_demo_offline_netiface/.pico_rp2350_tinyusb.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.pico_rp2350_tinyusb.generate rename to examples/Wippersnapper_demo_offline_netiface/.pico_rp2350_tinyusb.test.skip diff --git a/examples/Wippersnapper_demo_offline/.picow_rp2040_tinyusb.test.skip b/examples/Wippersnapper_demo_offline_netiface/.picow_rp2040_tinyusb.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.picow_rp2040_tinyusb.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.picow_rp2040_tinyusb.test.skip diff --git a/examples/Wippersnapper_demo_offline/.pyportal_tinyusb.test.skip b/examples/Wippersnapper_demo_offline_netiface/.pyportal_tinyusb.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.pyportal_tinyusb.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.pyportal_tinyusb.test.skip diff --git a/examples/Wippersnapper_demo_offline/.pyportal_titano_tinyusb.test.skip b/examples/Wippersnapper_demo_offline_netiface/.pyportal_titano_tinyusb.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.pyportal_titano_tinyusb.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.pyportal_titano_tinyusb.test.skip diff --git a/examples/Wippersnapper_demo_offline/.qtpy_esp32.test.skip b/examples/Wippersnapper_demo_offline_netiface/.qtpy_esp32.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.qtpy_esp32.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.qtpy_esp32.test.skip diff --git a/examples/Wippersnapper_demo_offline/.qtpy_esp32c3.test.skip b/examples/Wippersnapper_demo_offline_netiface/.qtpy_esp32c3.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.qtpy_esp32c3.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.qtpy_esp32c3.test.skip diff --git a/examples/Wippersnapper_demo_offline/.qtpy_esp32s2.test.skip b/examples/Wippersnapper_demo_offline_netiface/.qtpy_esp32s2.generate similarity index 100% rename from examples/Wippersnapper_demo_offline/.qtpy_esp32s2.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.qtpy_esp32s2.generate diff --git a/examples/Wippersnapper_demo_offline/.qtpy_esp32s3.test.skip b/examples/Wippersnapper_demo_offline_netiface/.qtpy_esp32s3.generate similarity index 100% rename from examples/Wippersnapper_demo_offline/.qtpy_esp32s3.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.qtpy_esp32s3.generate diff --git a/examples/Wippersnapper_demo_offline/.qtpy_esp32s3_n4r2.test.skip b/examples/Wippersnapper_demo_offline_netiface/.qtpy_esp32s3_n4r2.generate similarity index 100% rename from examples/Wippersnapper_demo_offline/.qtpy_esp32s3_n4r2.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.qtpy_esp32s3_n4r2.generate diff --git a/examples/Wippersnapper_demo_offline/.wippersnapper_feather_esp32.test.skip b/examples/Wippersnapper_demo_offline_netiface/.wippersnapper_feather_esp32.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.wippersnapper_feather_esp32.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.wippersnapper_feather_esp32.test.skip diff --git a/examples/Wippersnapper_demo_offline/.wippersnapper_qtpy_esp32c3.test.skip b/examples/Wippersnapper_demo_offline_netiface/.wippersnapper_qtpy_esp32c3.test.skip similarity index 100% rename from examples/Wippersnapper_demo_offline/.wippersnapper_qtpy_esp32c3.test.skip rename to examples/Wippersnapper_demo_offline_netiface/.wippersnapper_qtpy_esp32c3.test.skip diff --git a/examples/Wippersnapper_demo_offline/Wippersnapper_demo_offline.ino b/examples/Wippersnapper_demo_offline_netiface/Wippersnapper_demo_offline_netiface.ino similarity index 95% rename from examples/Wippersnapper_demo_offline/Wippersnapper_demo_offline.ino rename to examples/Wippersnapper_demo_offline_netiface/Wippersnapper_demo_offline_netiface.ino index 07ecfcf1e..7acf22341 100644 --- a/examples/Wippersnapper_demo_offline/Wippersnapper_demo_offline.ino +++ b/examples/Wippersnapper_demo_offline_netiface/Wippersnapper_demo_offline_netiface.ino @@ -10,7 +10,7 @@ // All text above must be included in any redistribution. #include "ws_adapters.h" -ws_adapter_offline wipper; +ws_adapter_wifi wipper; #define WS_DEBUG // Enable debug output! void setup() { diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32_v2.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32_v2.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32_v2.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32_v2_debug.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32_v2_debug.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32_v2_debug.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_debug.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_debug.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_debug.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_reverse_tft.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_reverse_tft.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_reverse_tft.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_tft.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_tft.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_tft.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_tft_debug.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_tft_debug.skip new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_tft_debug.skip @@ -0,0 +1,2 @@ + + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_tft_debug.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_tft_debug.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s2_tft_debug.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_4mbflash_2mbpsram.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_4mbflash_2mbpsram.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_4mbflash_2mbpsram.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_4mbflash_2mbpsram_debug.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_4mbflash_2mbpsram_debug.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_4mbflash_2mbpsram_debug.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_debug.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_debug.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_debug.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_reverse_tft.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_reverse_tft.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_reverse_tft.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_tft.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_tft.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_tft.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_tft_debug.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_tft_debug.test.skip new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp32s3_tft_debug.test.skip @@ -0,0 +1,2 @@ + + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp8266.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp8266.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_esp8266.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_rp2040_adalogger_tinyusb.generate b/examples/Wippersnapper_demo_offline_nonetiface/.feather_rp2040_adalogger_tinyusb.generate new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_rp2040_adalogger_tinyusb.generate @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.feather_s2_tinyusb.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.feather_s2_tinyusb.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.feather_s2_tinyusb.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.funhouse.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.funhouse.test.skip new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.funhouse.test.skip @@ -0,0 +1,2 @@ + + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.funhouse_noota.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.funhouse_noota.test.skip new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.funhouse_noota.test.skip @@ -0,0 +1,2 @@ + + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.itsybitsy_esp32.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.itsybitsy_esp32.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.itsybitsy_esp32.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.magtag.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.magtag.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.magtag.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.metro_esp32s3.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.metro_esp32s3.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.metro_esp32s3.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.metro_esp32s3_debug.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.metro_esp32s3_debug.test.skip new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.metro_esp32s3_debug.test.skip @@ -0,0 +1,2 @@ + + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.metro_m4_airliftlite_tinyusb.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.metro_m4_airliftlite_tinyusb.test.skip new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.metro_m4_airliftlite_tinyusb.test.skip @@ -0,0 +1,2 @@ + + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.metro_rp2350_tinyusb.generate b/examples/Wippersnapper_demo_offline_nonetiface/.metro_rp2350_tinyusb.generate new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.metro_rp2350_tinyusb.generate @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.metroesp32s2.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.metroesp32s2.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.metroesp32s2.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.metroesp32s2_debug.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.metroesp32s2_debug.test.skip new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.metroesp32s2_debug.test.skip @@ -0,0 +1,2 @@ + + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.pico_rp2040_tinyusb.generate b/examples/Wippersnapper_demo_offline_nonetiface/.pico_rp2040_tinyusb.generate new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.pico_rp2040_tinyusb.generate @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.pico_rp2350_tinyusb.generate b/examples/Wippersnapper_demo_offline_nonetiface/.pico_rp2350_tinyusb.generate new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.pico_rp2350_tinyusb.generate @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.picow_rp2040_tinyusb.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.picow_rp2040_tinyusb.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.picow_rp2040_tinyusb.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.pyportal_tinyusb.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.pyportal_tinyusb.test.skip new file mode 100644 index 000000000..b28b04f64 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.pyportal_tinyusb.test.skip @@ -0,0 +1,3 @@ + + + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.pyportal_titano_tinyusb.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.pyportal_titano_tinyusb.test.skip new file mode 100644 index 000000000..b28b04f64 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.pyportal_titano_tinyusb.test.skip @@ -0,0 +1,3 @@ + + + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32c3.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32c3.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32c3.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32s2.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32s2.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32s2.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32s3.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32s3.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32s3.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32s3_n4r2.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32s3_n4r2.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.qtpy_esp32s3_n4r2.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.wippersnapper_feather_esp32.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.wippersnapper_feather_esp32.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.wippersnapper_feather_esp32.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/.wippersnapper_qtpy_esp32c3.test.skip b/examples/Wippersnapper_demo_offline_nonetiface/.wippersnapper_qtpy_esp32c3.test.skip new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/.wippersnapper_qtpy_esp32c3.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo_offline_nonetiface/Wippersnapper_demo_offline_nonetiface.ino b/examples/Wippersnapper_demo_offline_nonetiface/Wippersnapper_demo_offline_nonetiface.ino new file mode 100644 index 000000000..8ddacaa21 --- /dev/null +++ b/examples/Wippersnapper_demo_offline_nonetiface/Wippersnapper_demo_offline_nonetiface.ino @@ -0,0 +1,24 @@ +// Adafruit IO WipperSnapper - Offline Mode +// USE ONLY WITH DEVICES WITH A NETWORK ADAPTER LIKE ESP32-x +// +// Adafruit invests time and resources providing this open source code. +// Please support Adafruit and open source hardware by purchasing +// products from Adafruit! +// +// Brent Rubell for Adafruit Industries, 2025 +// +// All text above must be included in any redistribution. + +#include "ws_adapters.h" +ws_adapter_offline wipper; +#define WS_DEBUG // Enable debug output! + +void setup() { + Serial.begin(115200); + wipper.provision(); + wipper.connect(); +} + +void loop() { + wipper.run(); +} \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index bc523e30e..6e3048d18 100644 --- a/platformio.ini +++ b/platformio.ini @@ -132,7 +132,7 @@ lib_compat_mode = soft ; can be strict once pio detects SleepyDog on RP2040 extends = common:esp32 board = esp32dev board_build.partitions = default_8MB.csv -build_flags = -DARDUINO_ESP32_DEV -DOFFLINE_MODE_DEBUG -DOFFLINE_MODE_WOKWI +build_flags = -DARDUINO_ESP32_DEV -DOFFLINE_MODE_DEBUG -DOFFLINE_MODE_WOKWI -DBUILD_OFFLINE_ONLY board_build.filesystem = littlefs upload_speed = 921600 @@ -165,7 +165,7 @@ board_build.filesystem = littlefs [env:featheresp32s2] extends = common:esp32 board = featheresp32-s2 -build_flags = -DARDUINO_ADAFRUIT_FEATHER_ESP32S2 -DBOARD_HAS_PSRAM +build_flags = -DARDUINO_ADAFRUIT_FEATHER_ESP32S2 -DBOARD_HAS_PSRAM -DBUILD_OFFLINE_ONLY board_build.partitions = tinyuf2-partitions-4MB-noota.csv ;board_build.partitions = tinyuf2-partitions-4MB.csv ;build_type = debug @@ -434,7 +434,7 @@ platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop board = adafruit_feather_adalogger platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git board_build.filesystem_size = 0.5m -build_flags = -DUSE_TINYUSB -DBUILD_OFFLINE_ONLY +build_flags = -DUSE_TINYUSB ; Once https://github.com/platformio/platformio-core > 6.1.11 these can be removed lib_ignore = WiFiNINA, WiFi101, Adafruit Zero DMA Library diff --git a/src/Wippersnapper_Boards.h b/src/Wippersnapper_Boards.h index 01babf8a5..8d4b892e0 100644 --- a/src/Wippersnapper_Boards.h +++ b/src/Wippersnapper_Boards.h @@ -7,7 +7,7 @@ * please support Adafruit and open-source hardware by purchasing * products from Adafruit! * - * Copyright (c) Brent Rubell 2020-2022 for Adafruit Industries. + * Copyright (c) Brent Rubell 2020-2025 for Adafruit Industries. * * BSD license, all text here must be included in any redistribution. * @@ -22,18 +22,21 @@ #define USE_STATUS_NEOPIXEL #define STATUS_NEOPIXEL_PIN 2 #define STATUS_NEOPIXEL_NUM 1 +#define SD_CS_PIN 10 #elif defined(ADAFRUIT_PYPORTAL_M4_TITANO) #define BOARD_ID "pyportal-titano-tinyusb" #define USE_TINYUSB #define USE_STATUS_NEOPIXEL #define STATUS_NEOPIXEL_PIN 2 #define STATUS_NEOPIXEL_NUM 1 +#define SD_CS_PIN 10 #elif defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE) #define BOARD_ID "metro-m4-airliftlite-tinyusb" #define USE_TINYUSB #define USE_STATUS_NEOPIXEL #define STATUS_NEOPIXEL_PIN 40 #define STATUS_NEOPIXEL_NUM 1 +#define SD_CS_PIN 10 #elif defined(ARDUINO_FUNHOUSE_ESP32S2) #define BOARD_ID "funhouse" ///< Board ID #define USE_TINYUSB ///< Enable TinyUSB @@ -44,6 +47,7 @@ #define STATUS_DOTSTAR_NUM 5 ///< Number of DotStar LEDs #define STATUS_DOTSTAR_COLOR_ORDER DOTSTAR_GBR ///< DotStar Color Order #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 10 #elif defined(ARDUINO_METRO_ESP32S2) #define BOARD_ID "metroesp32s2" #define USE_TINYUSB @@ -51,6 +55,7 @@ #define STATUS_NEOPIXEL_PIN 45 #define STATUS_NEOPIXEL_NUM 1 #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 10 #elif defined(ARDUINO_METRO_ESP32S3) #define BOARD_ID "metroesp32s3" #define USE_TINYUSB @@ -58,6 +63,7 @@ #define STATUS_NEOPIXEL_PIN 46 #define STATUS_NEOPIXEL_NUM 1 #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 #elif defined(ARDUINO_MAGTAG29_ESP32S2) #define BOARD_ID "magtag" #define USE_TINYUSB @@ -65,6 +71,7 @@ #define STATUS_NEOPIXEL_PIN 1 #define STATUS_NEOPIXEL_NUM 4 #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 10 #elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2) #define BOARD_ID "feather-esp32s2" #define USE_TINYUSB @@ -72,6 +79,7 @@ #define STATUS_NEOPIXEL_PIN 33 #define STATUS_NEOPIXEL_NUM 1 #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 10 #elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2_TFT) #define BOARD_ID "feather-esp32s2-tft" #define USE_TINYUSB @@ -80,6 +88,7 @@ #define STATUS_NEOPIXEL_NUM 1 #define PIN_I2C_POWER_INVERTED 7 #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 10 #elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2_REVTFT) #define BOARD_ID "feather-esp32s2-reverse-tft" #define USE_TINYUSB @@ -87,12 +96,14 @@ #define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL #define STATUS_NEOPIXEL_NUM NEOPIXEL_NUM #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 10 #elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3_NOPSRAM) #define BOARD_ID "feather-esp32s3" #define USE_TINYUSB #define USE_STATUS_NEOPIXEL #define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL #define STATUS_NEOPIXEL_NUM NEOPIXEL_NUM +#define SD_CS_PIN 33 #elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3) #define BOARD_ID "feather-esp32s3-4mbflash-2mbpsram" #define USE_TINYUSB @@ -100,6 +111,7 @@ #define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL #define STATUS_NEOPIXEL_NUM NEOPIXEL_NUM #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 #elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3_TFT) #define BOARD_ID "feather-esp32s3-tft" #define USE_TINYUSB @@ -107,6 +119,7 @@ #define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL #define STATUS_NEOPIXEL_NUM NEOPIXEL_NUM #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 #elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3_REVTFT) #define BOARD_ID "feather-esp32s3-reverse-tft" #define USE_TINYUSB @@ -114,6 +127,7 @@ #define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL #define STATUS_NEOPIXEL_NUM NEOPIXEL_NUM #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 #elif defined(ARDUINO_ADAFRUIT_QTPY_ESP32S2) #define BOARD_ID "qtpy-esp32s2" #define USE_TINYUSB @@ -122,6 +136,7 @@ #define STATUS_NEOPIXEL_NUM 1 #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation #define I2c_STEMMA_WIRE1 +#define SD_CS_PIN 10 #elif defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM) #define BOARD_ID "qtpy-esp32s3" #define USE_TINYUSB @@ -129,6 +144,7 @@ #define STATUS_NEOPIXEL_NUM 1 #define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL #define I2c_STEMMA_WIRE1 +#define SD_CS_PIN 33 #elif defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3_N4R2) #define BOARD_ID "qtpy-esp32s3-n4r2" #define USE_TINYUSB @@ -137,17 +153,20 @@ #define STATUS_NEOPIXEL_NUM 1 #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation #define I2c_STEMMA_WIRE1 +#define SD_CS_PIN 33 #elif defined(ARDUINO_ADAFRUIT_QTPY_ESP32C3) #define BOARD_ID "qtpy-esp32c3" #define USE_LITTLEFS #define USE_STATUS_NEOPIXEL #define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL #define STATUS_NEOPIXEL_NUM 1 +#define SD_CS_PIN 33 #elif defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) #define BOARD_ID "feather-esp8266" #define USE_LITTLEFS #define USE_STATUS_LED #define STATUS_LED_PIN 0 +#define SD_CS_PIN 33 #elif defined(ARDUINO_ADAFRUIT_ITSYBITSY_ESP32) #define BOARD_ID "itsybitsy-esp32" #define USE_LITTLEFS @@ -155,15 +174,18 @@ #define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL #define STATUS_NEOPIXEL_NUM 1 #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 #elif defined(ARDUINO_FEATHER_ESP32) #define BOARD_ID "feather-esp32" #define USE_LITTLEFS #define USE_STATUS_LED #define STATUS_LED_PIN 13 +#define SD_CS_PIN 33 #elif defined(ARDUINO_ESP32_DEV) || defined(ESP32_DEV) #define BOARD_ID "feather-esp32" #define USE_STATUS_LED #define STATUS_LED_PIN 13 +#define SD_CS_PIN 33 #elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2) #define BOARD_ID "feather-esp32-v2" #define USE_LITTLEFS @@ -171,6 +193,7 @@ #define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL #define STATUS_NEOPIXEL_NUM 1 #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 #elif defined(ARDUINO_ADAFRUIT_QTPY_ESP32_PICO) #define BOARD_ID "qtpy-esp32" #define USE_LITTLEFS @@ -179,29 +202,35 @@ #define STATUS_NEOPIXEL_NUM 1 #define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation #define I2c_STEMMA_WIRE1 +#define SD_CS_PIN 33 #elif defined(ARDUINO_SAMD_NANO_33_IOT) #define BOARD_ID "nano-33-iot" #define USE_STATUS_LED #define STATUS_LED_PIN 13 +#define SD_CS_PIN 33 #elif defined(ARDUINO_SAMD_MKRWIFI1010) #define BOARD_ID "mkrwifi1010" #define USE_STATUS_LED #define STATUS_LED_PIN 6 +#define SD_CS_PIN 33 #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) #define BOARD_ID "rpi-pico-w" #define USE_TINYUSB #define USE_STATUS_LED #define STATUS_LED_PIN 32 +#define SD_CS_PIN 33 #elif defined(ARDUINO_RASPBERRY_PI_PICO) #define BOARD_ID "rpi-pico" #define USE_TINYUSB #define USE_STATUS_LED #define STATUS_LED_PIN LED_BUILTIN +#define SD_CS_PIN 33 #elif defined(ARDUINO_RASPBERRY_PI_PICO_2) #define BOARD_ID "rpi-pico-2" #define USE_TINYUSB #define USE_STATUS_LED #define STATUS_LED_PIN LED_BUILTIN +#define SD_CS_PIN 33 #elif defined(ARDUINO_ADAFRUIT_FEATHER_RP2040_ADALOGGER) #define BOARD_ID "feather-rp2040-adalogger" #define USE_TINYUSB @@ -209,6 +238,7 @@ #define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL #define STATUS_NEOPIXEL_NUM 1 #define SD_USE_SPI_1 +#define SD_CS_PIN 23 #elif defined(ARDUINO_ADAFRUIT_METRO_RP2350) #define BOARD_ID "metro-rp2350" #define USE_TINYUSB @@ -216,6 +246,7 @@ #define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL #define STATUS_NEOPIXEL_NUM NUM_NEOPIXEL #define SD_USE_SPI_1 +#define SD_CS_PIN 39 #else #warning "Board type not identified within Wippersnapper_Boards.h!" #endif diff --git a/src/Wippersnapper_V2.cpp b/src/Wippersnapper_V2.cpp index 1814aa0e5..5f3a62376 100644 --- a/src/Wippersnapper_V2.cpp +++ b/src/Wippersnapper_V2.cpp @@ -78,35 +78,34 @@ void Wippersnapper_V2::provision() { // Initialize the filesystem #ifdef USE_TINYUSB - _fileSystemV2 = new Wippersnapper_FS(); + WsV2._fileSystemV2 = new Wippersnapper_FS(); #elif defined(USE_LITTLEFS) - _littleFSV2 = new WipperSnapper_LittleFS(); + WsV2._littleFSV2 = new WipperSnapper_LittleFS(); #endif // Determine if app is in SDLogger mode #ifdef USE_TINYUSB - _fileSystemV2->GetSDCSPin(); + WsV2._fileSystemV2->GetPinSDCS(); #elif defined(USE_LITTLEFS) - _littleFSV2->GetSDCSPin(); + WsV2._littleFSV2->GetPinSDCS(); #elif defined(OFFLINE_MODE_WOKWI) WsV2.pin_sd_cs = 15; #endif + WsV2._sdCardV2 = new ws_sdcard(); if (WsV2._sdCardV2->isSDCardInitialized()) { return; // SD card initialized, cede control back to loop() } else { -#ifdef BUILD_OFFLINE_ONLY haltErrorV2("SD initialization failed.\nDo not reformat the card!\nIs the " "card correctly inserted?\nIs there a wiring/soldering " "problem\nIs the config.json file malformed?"); -#endif // SD card not initialized, so just continue with online-mode provisioning } #ifdef USE_DISPLAY // Initialize the display displayConfig config; - WsV2._fileSystemV2->parseDisplayConfig(config); + WsV2._fileSystemV2->ParseFileDisplayCfg(config); WsV2._display = new ws_display_driver(config); // Begin display if (!WsV2._display->begin()) { @@ -125,9 +124,9 @@ void Wippersnapper_V2::provision() { #endif #ifdef USE_TINYUSB - _fileSystemV2->parseSecrets(); + WsV2._fileSystemV2->ParseFileSecrets(); #elif defined(USE_LITTLEFS) - _littleFSV2->parseSecrets(); + WsV2._littleFSV2->ParseFileSecrets(); #else check_valid_ssid(); // non-fs-backed, sets global credentials within network // iface @@ -714,7 +713,7 @@ void Wippersnapper_V2::errorWriteHangV2(String error) { // Print error WS_DEBUG_PRINTLN(error); #ifdef USE_TINYUSB - _fileSystemV2->writeToBootOut(error.c_str()); + WsV2._fileSystemV2->WriteFileBoot(error.c_str()); TinyUSBDevice.attach(); delay(500); #endif @@ -1222,28 +1221,33 @@ void Wippersnapper_V2::connect() { // If we are running in offline mode, we skip the network setup // and MQTT connection process and jump to the offline device config process // NOTE: After this, bail out of this function and run the app loop!!! - if (WsV2._sdCardV2->isModeOffline() == true) { - WS_DEBUG_PRINTLN("[Offline] Running device configuration..."); + if (WsV2._sdCardV2->isModeOffline()) { + WS_DEBUG_PRINTLN("[APP] Running device configuration..."); // If debug mode, wait for serial config #ifdef OFFLINE_MODE_DEBUG WsV2._sdCardV2->waitForSerialConfig(); #endif + WS_DEBUG_PRINTLN("[APP] Performing I2C Autoscan..."); + WsV2._i2c_controller->ScanI2cBus(true); // Parse the JSON file - if (!WsV2._sdCardV2->parseConfigFile()) - haltErrorV2("Failed to parse config.json!"); - WS_DEBUG_PRINTLN("[Offline] Attempting to configure hardware..."); + if (!WsV2._sdCardV2->ParseFileConfig()) + haltErrorV2("[APP] Failed to parse config.json!"); + WS_DEBUG_PRINTLN("[APP] Attempting to configure hardware..."); #ifndef OFFLINE_MODE_DEBUG if (!WsV2._sdCardV2->CreateNewLogFile()) haltErrorV2("Unable to create new .log file on SD card!"); #endif // Call the TL signal decoder to parse the incoming JSON data callDecodeB2D(); - WS_DEBUG_PRINTLN("[Offline] Hardware configured, skipping network setup " - "and running app..."); +#ifndef OFFLINE_MODE_WOKWI + WsV2._fileSystemV2->WriteFileConfig(); +#endif // OFFLINE_MODE_WOKWI used for CI test simulations, lacks TinyUSB + WS_DEBUG_PRINTLN("[APP] Hardware configured!"); // Blink status LED to green to indicate successful configuration - setStatusLEDColor(0x00A300, WsV2.status_pixel_brightnessV2 * 255.0); + setStatusLEDColor(0x00A300, WsV2.status_pixel_brightnessV2); delay(500); - setStatusLEDColor(0x000000, WsV2.status_pixel_brightnessV2 * 255.0); + setStatusLEDColor(0x000000, WsV2.status_pixel_brightnessV2); + WS_DEBUG_PRINTLN("[APP] Begin loop()"); return; } else { WS_DEBUG_PRINTLN("Running in online mode..."); diff --git a/src/Wippersnapper_V2.h b/src/Wippersnapper_V2.h index 77478e930..f573ea377 100644 --- a/src/Wippersnapper_V2.h +++ b/src/Wippersnapper_V2.h @@ -70,6 +70,7 @@ } // Cpp STD +#include #include #include #include @@ -127,7 +128,8 @@ #endif #define WS_VERSION \ - "1.0.0-offline-beta.1" ///< WipperSnapper app. version (semver-formatted) + "1.0.0-offline-beta.3" ///< WipperSnapper app. version + ///< (semver-formatted) #define WS_WDT_TIMEOUT 60000 ///< WDT timeout #define WS_MAX_ALT_WIFI_NETWORKS 3 ///< Maximum number of alternative networks diff --git a/src/Wippersnapper_demo.ino b/src/Wippersnapper_demo.ino index e8617803d..73628abdc 100644 --- a/src/Wippersnapper_demo.ino +++ b/src/Wippersnapper_demo.ino @@ -10,16 +10,15 @@ #include "ws_adapters.h" ws_adapter_wifi wipper; -// Uncomment the following line to use the offline adapter for Pico -// ws_adapter_offline wipper; + #define WS_DEBUG // Enable debug output! void setup() { Serial.begin(115200); - while (!Serial) - delay(10); wipper.provision(); wipper.connect(); } -void loop() { wipper.run(); } \ No newline at end of file +void loop() { + wipper.run(); +} \ No newline at end of file diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index ebba20477..1eaf24238 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -344,6 +344,83 @@ static const std::map I2cFactory = { return new drvVl6180x(i2c, addr, mux_channel, driver_name); }}}; ///< I2C driver factory +static const std::unordered_map> + map_address_to_drivers = { + {0x0B, {"lc709203f"}}, + {0x12, {"pmsa003i"}}, + {0x13, {"vncl4020"}}, + {0x18, {"ds2484", "mcp9808", "mprls"}}, + {0x19, {"mcp9808"}}, + {0x1A, {"mcp9808"}}, + {0x1B, {"mcp9808"}}, + {0x1C, {"mcp9808"}}, + {0x1D, {"mcp9808"}}, + {0x1E, {"mcp9808"}}, + {0x1F, {"mcp9808"}}, + {0x23, {"bh1750"}}, + {0x28, {"pct2075"}}, + {0x29, + {"ltr303", "pct2075", "tsl2591", "veml7700", "vl53l1x", "vl53l4cd", + "vl53l4cx", "vl6180x"}}, + {0x2A, {"nau7802"}}, + {0x38, {"aht20", "max17048"}}, + {0x39, {"tsl2591"}}, + {0x40, {"htu21d", "ina219", "ms8607", "si7021", "stemma_soil"}}, + {0x41, {"ina219"}}, + {0x44, {"sht3x", "sht4x"}}, + {0x45, {"sht3x"}}, + {0x48, {"adt7410", "pct2075", "tmp117"}}, + {0x49, {"adt7410", "pct2075", "tmp117", "tsl2591"}}, + {0x4A, {"adt7410", "pct2075", "tmp117"}}, + {0x4B, {"adt7410", "pct2075", "tmp117"}}, + {0x4C, {"pct2075"}}, + {0x4D, {"pct2075"}}, + {0x4E, {"pct2075"}}, + {0x4F, {"pct2075"}}, + {0x52, {"ens160"}}, + {0x53, {"ens160", "ltr390"}}, + {0x59, {"sgp40"}}, + {0x5C, {"bh1750", "lps22hb", "lps25hb"}}, + {0x5D, {"lps22hb", "lps25hb"}}, + {0x5F, {"hts2221"}}, + {0x60, {"mpl115a2", "vncl4040"}}, + {0x61, {"scd30"}}, + {0x62, {"scd40"}}, + {0x68, {"mcp3421"}}, + {0x69, {"sen50"}}, + {0x70, {"pct2075", "shtc3"}}, + {0x71, {"pct2075"}}, + {0x72, {"pct2075"}}, + {0x73, {"pct2075"}}, + {0x74, {"pct2075"}}, + {0x75, {"pct2075"}}, + {0x76, + {"bme280", "bme680", "bmp280", "bmp388", "bmp390", "dps310", "ms8607", + "pct2075"}}, + {0x77, + {"bme280", "bme680", "bmp280", "bmp388", "bmp390", "dps310", + "pct2075"}}}; ///< I2C address to driver map + +/***********************************************************************/ +/*! + @brief Obtains possible candidate drivers for a given I2C address. + @param addr + The desired I2C address. + @returns A vector of pointers to candidate drivers. +*/ +/***********************************************************************/ +std::vector GetDriversForAddress(uint16_t addr) { + std::vector candidates; + std::unordered_map>::const_iterator + candidate = map_address_to_drivers.find(addr); + + if (candidate != map_address_to_drivers.end()) { + candidates = candidate->second; + } + + return candidates; +} + /***********************************************************************/ /*! @brief Creates an I2C driver by name @@ -384,7 +461,6 @@ I2cController::I2cController() { _i2c_model = new I2cModel(); // Initialize the default I2C bus _i2c_bus_default = new I2cHardware(); - _i2c_bus_default->InitBus(true); } /***********************************************************************/ @@ -511,6 +587,46 @@ bool I2cController::InitMux(const char *name, uint32_t address, return true; } +/***********************************************************************/ +/*! + @brief Checks if a driver has already been initialized with the + given device descriptor. + @param device_descriptor + The I2cDeviceDescriptor message. + @returns True if a driver has already been initialized, False + otherwise. +*/ +/***********************************************************************/ +bool I2cController::IsDriverInitialized( + wippersnapper_i2c_I2cDeviceDescriptor &device_descriptor) { + // Before we do anything, check if a driver has been already initialized with + // the device_descriptor if so, we log and skip + for (auto &driver : _i2c_drivers) { + // Do they share the same address? + if (driver->GetAddress() == device_descriptor.i2c_device_address) { + // Okay - do they sit on different i2c buses? + bool is_driver_bus_alt = driver->HasAltI2CBus(); + bool is_device_bus_alt = + (strcmp(device_descriptor.i2c_bus_scl, "default") != 0) || + (strcmp(device_descriptor.i2c_bus_sda, "default") != 0); + // Bus descriptors do not match, so we haven't initialized this candidate + if (is_driver_bus_alt != is_device_bus_alt) + continue; + + // What about the MUX? + if (driver->HasMux() && + driver->GetMuxAddress() == device_descriptor.i2c_mux_address && + driver->GetMuxChannel() != device_descriptor.i2c_mux_channel) { + continue; + } + + WS_DEBUG_PRINTLN("[i2c] Descriptor already initialized..."); + return true; + } + } + return false; +} + /***********************************************************************/ /*! @brief Implements handling for a I2cDeviceAddOrReplace message @@ -540,6 +656,12 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) { wippersnapper_i2c_I2cDeviceDescriptor device_descriptor = _i2c_model->GetI2cDeviceAddOrReplaceMsg()->i2c_device_description; + // Did the driver initialize correctly? + if (IsDriverInitialized(device_descriptor)) { + WS_DEBUG_PRINTLN("[i2c] Driver already initialized, skipping..."); + return true; + } + // TODO [Online]: Handle Replace messages by implementing the Remove handler // first...then proceed to adding a new device @@ -575,7 +697,8 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) { if ((strcmp(device_name, "pca9546") == 0) || (strcmp(device_name, "pca9548") == 0)) { WS_DEBUG_PRINT("[i2c] Initializing MUX driver..."); - if (!InitMux(device_name, device_descriptor.i2c_mux_address, use_alt_bus)) { + if (!InitMux(device_name, device_descriptor.i2c_device_address, + use_alt_bus)) { // TODO [Online]: Publish back out to IO here! WsV2.haltErrorV2("[i2c] Failed to initialize MUX driver!", WS_LED_STATUS_ERROR_RUNTIME, false); @@ -588,8 +711,6 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) { // I2cDeviceAddorReplace message if (device_descriptor.i2c_mux_address != 0x00) { if (_i2c_bus_alt->HasMux() || _i2c_bus_default->HasMux()) { - WS_DEBUG_PRINT("[i2c] Configuring MUX channel: "); - WS_DEBUG_PRINTLN(device_descriptor.i2c_mux_channel); ConfigureMuxChannel(device_descriptor.i2c_mux_channel, use_alt_bus); did_set_mux_ch = true; } else { @@ -599,7 +720,6 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) { } } - WS_DEBUG_PRINTLN("Creating a new I2C driver"); // Assign I2C bus TwoWire *bus = nullptr; if (use_alt_bus) { @@ -608,51 +728,107 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) { bus = _i2c_bus_default->GetBus(); } - drvBase *drv = CreateI2CDriverByName( - device_name, bus, device_descriptor.i2c_device_address, - device_descriptor.i2c_mux_channel, device_status); - if (drv == nullptr) { - WS_DEBUG_PRINTLN("[i2c] ERROR: I2C driver type not found or unsupported!"); - if (WsV2._sdCardV2->isModeOffline()) { - WsV2.haltErrorV2("[i2c] Driver failed to initialize!\n\tDid you set " - "the correct value for i2cDeviceName?\n\tDid you set " - "the correct value for" - "i2cDeviceAddress?", - WS_LED_STATUS_ERROR_RUNTIME, false); + drvBase *drv = nullptr; + WS_DEBUG_PRINTLN("[i2c] Creating driver: "); + WS_DEBUG_PRINTLN(device_name); + if (strcmp(device_name, SCAN_DEVICE) == 0) { + WS_DEBUG_PRINTLN("Attempting to autoconfig device found in scan..."); + // Get all possible driver candidates for this address + WS_DEBUG_PRINT("[i2c] Obtaining driver candidates @ 0x"); + WS_DEBUG_PRINTLN(device_descriptor.i2c_device_address, HEX); + if (device_descriptor.i2c_device_address == 0x68 || + device_descriptor.i2c_device_address == 0x70) { + WS_DEBUG_PRINTLN("[i2c] Device address is shared with RTC/MUX, can not " + "auto-init, skipping!"); + return true; } - } - // Attempt to initialize the driver - if (did_set_mux_ch) { - drv->SetMuxAddress(device_descriptor.i2c_mux_address); - WS_DEBUG_PRINTLN("[i2c] Set driver to use MUX"); - } - if (use_alt_bus) { - drv->EnableAltI2CBus(_i2c_model->GetI2cDeviceAddOrReplaceMsg() - ->i2c_device_description.i2c_bus_scl, - _i2c_model->GetI2cDeviceAddOrReplaceMsg() - ->i2c_device_description.i2c_bus_sda); - WS_DEBUG_PRINTLN("[i2c] Set driver to use Alt I2C bus"); - } - // Configure the driver - drv->EnableSensorReads( - _i2c_model->GetI2cDeviceAddOrReplaceMsg()->i2c_device_sensor_types, - _i2c_model->GetI2cDeviceAddOrReplaceMsg()->i2c_device_sensor_types_count); - drv->SetSensorPeriod( - _i2c_model->GetI2cDeviceAddOrReplaceMsg()->i2c_device_period); - if (!drv->begin()) { - if (WsV2._sdCardV2->isModeOffline()) { - WsV2.haltErrorV2("[i2c] Driver failed to initialize!\n\tDid you set " - "the correct value for i2cDeviceName?\n\tDid you set " - "the correct value for" - "i2cDeviceAddress?", - WS_LED_STATUS_ERROR_RUNTIME, false); + std::vector candidate_drivers = + GetDriversForAddress(device_descriptor.i2c_device_address); + + // Probe each candidate to see if it communicates + bool did_find_driver = false; + for (const char *driverName : candidate_drivers) { + WS_DEBUG_PRINT("[i2c] Attempting to initialize candidate: "); + WS_DEBUG_PRINTLN(driverName); + drv = CreateI2CDriverByName( + driverName, bus, device_descriptor.i2c_device_address, + device_descriptor.i2c_mux_channel, device_status); + // Probe the driver to check if it communicates its init. sequence + // properly + if (!drv->begin()) { + delete drv; + drv = nullptr; + } else { + WS_DEBUG_PRINT("[i2c] Successfully initialized candidate: "); + WS_DEBUG_PRINTLN(driverName); + // set device_name to driverName + strcpy(device_name, driverName); + // Use the "default" types from the sensor driver + drv->SetSensorTypes(true); + drv->SetPeriod(DEFAULT_SENSOR_PERIOD); +#ifndef OFFLINE_MODE_WOKWI + WsV2._fileSystemV2->AddI2cDeviceToFileConfig( + device_descriptor.i2c_device_address, driverName, + drv->GetSensorTypeStrings(), drv->GetNumSensorTypes()); +#endif + did_find_driver = true; + break; + } + } + if (!did_find_driver) { + WS_DEBUG_PRINTLN("[i2c] ERROR - Candidates exhausted, driver not found!"); + return true; // dont cause an error in the app + } + } else { + WS_DEBUG_PRINTLN("[i2c] Device in message/cfg file."); + // Create new driver + WS_DEBUG_PRINT("[i2c] Creating driver: "); + WS_DEBUG_PRINTLN(device_name); + drv = CreateI2CDriverByName( + device_name, bus, device_descriptor.i2c_device_address, + device_descriptor.i2c_mux_channel, device_status); + if (drv == nullptr) { + WS_DEBUG_PRINTLN( + "[i2c] ERROR: I2C driver type not found or unsupported!"); + return false; + } + + // Configure MUX and bus + if (did_set_mux_ch) { + drv->SetMuxAddress(device_descriptor.i2c_mux_address); } - } + if (use_alt_bus) { + drv->EnableAltI2CBus(_i2c_model->GetI2cDeviceAddOrReplaceMsg() + ->i2c_device_description.i2c_bus_scl, + _i2c_model->GetI2cDeviceAddOrReplaceMsg() + ->i2c_device_description.i2c_bus_sda); + } + // Configure the driver + drv->SetSensorTypes( + false, + _i2c_model->GetI2cDeviceAddOrReplaceMsg()->i2c_device_sensor_types, + _i2c_model->GetI2cDeviceAddOrReplaceMsg() + ->i2c_device_sensor_types_count); + + drv->SetPeriod( + _i2c_model->GetI2cDeviceAddOrReplaceMsg()->i2c_device_period); + + if (!drv->begin()) { + if (WsV2._sdCardV2->isModeOffline()) { + WS_DEBUG_PRINTLN("[i2c] Failed to initialize driver!\n\tDid you set " + "the correct value for i2cDeviceName?\n\tDid you set " + "the correct value for" + "i2cDeviceAddress?"); + } + return true; // don't cause an error during runtime if the device is not + // found + } + WS_DEBUG_PRINTLN("[i2c] Driver successfully initialized!"); + } + // Add the initialized driver _i2c_drivers.push_back(drv); - WS_DEBUG_PRINTLN("[i2c] Driver initialized and added to controller: "); - WS_DEBUG_PRINTLN(device_name); // If we're using a MUX, clear the channel for any subsequent bus // operations that may not involve the MUX @@ -675,6 +851,70 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) { return true; } +/***********************************************************************/ +/*! + @brief Scans the I2C bus for devices and stores the results. + @param default_bus + True to scan the default I2C bus, False to scan the + alternative I2C bus. + @returns True if the I2C bus was successfully scanned, False + if the scan failed with an error. +*/ +/***********************************************************************/ +bool I2cController::ScanI2cBus(bool default_bus = true) { + _i2c_bus_default->InitBus(default_bus); + _scan_results = wippersnapper_i2c_I2cBusScanned_init_zero; + if (!default_bus) + return _i2c_bus_alt->ScanBus(&_scan_results); + return _i2c_bus_default->ScanBus(&_scan_results); +} + +/***********************************************************************/ +/*! + @brief Checks if a device was found on the i2c bus. MUST be called + after scanning was performed. + @param address + The desired I2C device address. + @returns True if the device is on the bus, False otherwise. +*/ +/***********************************************************************/ +bool I2cController::WasDeviceScanned(uint32_t address) { + pb_size_t num_found_devices = _scan_results.i2c_bus_found_devices_count; + if (num_found_devices == 0) + return false; // no devices found on bus, or scan was not performed + + // Check if the device was found on the bus + for (pb_size_t i; i < num_found_devices; i++) { + if (_scan_results.i2c_bus_found_devices[i].i2c_device_address == address) + return true; // device found on bus! + } + return false; // exhausted all scanned devices, didn't find it +} + +/***********************************************************************/ +/*! + @brief Returns an i2c address of a device found on the bus. + @param index + The index of the scanned device within scan_results. + @returns The I2C device address of the scanned device. +*/ +/***********************************************************************/ +uint32_t I2cController::GetScanDeviceAddress(int index) { + if (index < 0 || index >= _scan_results.i2c_bus_found_devices_count) + return 0; + return _scan_results.i2c_bus_found_devices[index].i2c_device_address; +} + +/***********************************************************************/ +/*! + @brief Gets the number of devices found on the bus. + @returns The number of devices found on the bus. +*/ +/***********************************************************************/ +size_t I2cController::GetScanDeviceCount() { + return _scan_results.i2c_bus_found_devices_count; +} + /********************************************************************************/ /*! @brief Enables a MUX channel on the appropriate I2C bus. @@ -706,7 +946,7 @@ void I2cController::update() { for (auto *drv : _i2c_drivers) { // Does this driver have any enabled sensors? - size_t sensor_count = drv->GetEnabledSensorCnt(); + size_t sensor_count = drv->GetNumSensorTypes(); if (sensor_count == 0) continue; // bail out if driver has no sensors enabled diff --git a/src/components/i2c/controller.h b/src/components/i2c/controller.h index ac317d5a2..04e4b4662 100644 --- a/src/components/i2c/controller.h +++ b/src/components/i2c/controller.h @@ -67,6 +67,14 @@ #include "drivers/drvVncl4020.h" #include "drivers/drvVncl4040.h" +#define SCAN_DEVICE \ + "UNKNOWN_SCAN" ///< Name for I2C devices found by an i2c scan + +typedef struct { + uint32_t address; ///< I2C address of the device + bool is_initialized; ///< Flag to indicate if the device is initialized +} initialized_device_t; ///< Struct to hold initialized device info + class Wippersnapper_V2; ///< Forward declaration class I2cModel; ///< Forward declaration class I2cHardware; ///< Forward declaration @@ -95,12 +103,20 @@ class I2cController { bool IsBusStatusOK(bool is_alt_bus); bool InitMux(const char *name, uint32_t address, bool is_alt_bus); void ConfigureMuxChannel(uint32_t mux_channel, bool is_alt_bus); + bool ScanI2cBus(bool default_bus); + bool WasDeviceScanned(uint32_t address); + uint32_t GetScanDeviceAddress(int index); + size_t GetScanDeviceCount(); + bool + IsDriverInitialized(wippersnapper_i2c_I2cDeviceDescriptor &device_descriptor); private: I2cModel *_i2c_model; ///< Pointer to an I2C model object I2cHardware *_i2c_bus_default; ///< Pointer to the default I2C bus I2cHardware *_i2c_bus_alt; ///< Pointer to an alternative I2C bus std::vector _i2c_drivers; ///< Vector of ptrs to I2C device drivers + wippersnapper_i2c_I2cBusScanned + _scan_results; ///< Stores results of I2C bus scan }; extern Wippersnapper_V2 WsV2; ///< Wippersnapper V2 instance #endif // WS_I2C_CONTROLLER_H \ No newline at end of file diff --git a/src/components/i2c/drivers/drvAdt7410.h b/src/components/i2c/drivers/drvAdt7410.h index 3e6c33bfa..aa99773ec 100644 --- a/src/components/i2c/drivers/drvAdt7410.h +++ b/src/components/i2c/drivers/drvAdt7410.h @@ -79,6 +79,14 @@ class drvAdt7410 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + } + protected: Adafruit_ADT7410 *_ADT7410; ///< Pointer to ADT7410 temperature sensor object }; diff --git a/src/components/i2c/drivers/drvAhtx0.h b/src/components/i2c/drivers/drvAhtx0.h index e08226815..8643c4c67 100644 --- a/src/components/i2c/drivers/drvAhtx0.h +++ b/src/components/i2c/drivers/drvAhtx0.h @@ -106,6 +106,16 @@ class drvAhtx0 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 3; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY; + } + protected: Adafruit_AHTX0 *_aht; ///< Pointer to an AHTX0 object Adafruit_Sensor *_aht_temp = diff --git a/src/components/i2c/drivers/drvBase.h b/src/components/i2c/drivers/drvBase.h index c528730f9..02073df47 100644 --- a/src/components/i2c/drivers/drvBase.h +++ b/src/components/i2c/drivers/drvBase.h @@ -19,7 +19,8 @@ #include #include -#define NO_MUX_CH 0xFFFF; ///< No MUX channel specified +#define NO_MUX_CH 0xFFFF; ///< No MUX channel specified +#define DEFAULT_SENSOR_PERIOD 15.0f ///< Default sensor period, in seconds /**************************************************************************/ /*! @@ -54,6 +55,7 @@ class drvBase { _has_alt_i2c_bus = false; strcpy(_pin_scl, "default"); strcpy(_pin_sda, "default"); + _default_sensor_types_count = 0; } /*******************************************************************************/ @@ -106,6 +108,10 @@ class drvBase { */ /*******************************************************************************/ void EnableAltI2CBus(char *scl_pin, char *sda_pin) { + if (scl_pin == nullptr || sda_pin == nullptr) { + WS_DEBUG_PRINTLN("[drvBase] ERROR: Invalid Pins for Alt I2C bus!"); + return; + } strcpy(_pin_scl, scl_pin); strcpy(_pin_sda, sda_pin); _has_alt_i2c_bus = true; @@ -155,27 +161,61 @@ class drvBase { /*******************************************************************************/ /*! @brief Configures an i2c device's sensors. + @param use_default_types + Use default sensor types from the driver, rather than + the cfg file. @param sensor_types - Pointer to an array of SensorType objects. + The sensor types to use for the device. @param sensor_types_count The number of active sensors to read from the device. */ /*******************************************************************************/ - void EnableSensorReads(wippersnapper_sensor_SensorType *sensor_types, - size_t sensor_types_count) { - _sensors_count = sensor_types_count; + void SetSensorTypes(bool use_default_types = false, + wippersnapper_sensor_SensorType *sensor_types = nullptr, + size_t sensor_types_count = 0) { + + // Assign number of sensors + if (use_default_types) { + // Configure the driver with values from THE DRIVER + ConfigureDefaultSensorTypes(); + _sensors_count = _default_sensor_types_count; + } else { + // Configure the driver with values from THE CONFIG FILE + _sensors_count = sensor_types_count; + } + + // Fill sensor types with default values for (size_t i = 0; i < _sensors_count; i++) { - _sensors[i] = sensor_types[i]; + if (use_default_types) + _sensors[i] = _default_sensor_types[i]; + else + _sensors[i] = sensor_types[i]; + _sensor_type_strings[i] = SensorTypeToString(_sensors[i]); } } + /*******************************************************************************/ + /*! + @brief Gets a ptr to an array containing the sensor types, as strings. + @returns Pointer to an array of strings. + */ + /*******************************************************************************/ + const char **GetSensorTypeStrings() { return _sensor_type_strings; } + + /*******************************************************************************/ + /*! + @brief Configures a driver with the default SensorType(s) for the + device. + /*******************************************************************************/ + virtual void ConfigureDefaultSensorTypes() { return; } + /*******************************************************************************/ /*! @brief Gets the number of enabled sensors. @returns The number of enabled sensors. */ /*******************************************************************************/ - size_t GetEnabledSensorCnt() { return _sensors_count; } + size_t GetNumSensorTypes() { return _sensors_count; } /*******************************************************************************/ /*! @@ -193,11 +233,9 @@ class drvBase { seconds. */ /*******************************************************************************/ - void SetSensorPeriod(float period) { - if (period < 0) { - _sensor_period = 0; - return; - } + void SetPeriod(float period) { + if (period < 0) + _sensor_period = DEFAULT_SENSOR_PERIOD; _sensor_period = (unsigned long)(period * 1000.0f); } @@ -219,6 +257,14 @@ class drvBase { /*******************************************************************************/ ulong GetSensorPeriod() { return _sensor_period; } + /*******************************************************************************/ + /*! + @brief Gets the sensor's types + @returns A pointer to an array of SensorTypes. + */ + /*******************************************************************************/ + wippersnapper_sensor_SensorType *GetSensorTypes() { return _sensors; } + /*******************************************************************************/ /*! @brief Gets the sensor's previous period. @@ -711,6 +757,95 @@ class drvBase { wippersnapper_sensor_SensorType _sensors[15]; ///< Sensors attached to the device. + /***************************************************************************/ + /*! + @brief Converts a SensorType to a string. + @param type + The SensorType to convert. + @returns The string representation of the SensorType. + */ + /***************************************************************************/ + const char *SensorTypeToString(wippersnapper_sensor_SensorType type) { + switch (type) { + case wippersnapper_sensor_SensorType_SENSOR_TYPE_UNSPECIFIED: + return "unspecified"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_ACCELEROMETER: + return "accelerometer"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_MAGNETIC_FIELD: + return "magnetic-field"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_ORIENTATION: + return "orientation"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_GYROSCOPE: + return "gyroscope"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_LIGHT: + return "light"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_PRESSURE: + return "pressure"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_PROXIMITY: + return "proximity"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_GRAVITY: + return "gravity"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_LINEAR_ACCELERATION: + return "linear-acceleration"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_ROTATION_VECTOR: + return "rotation-vector"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY: + return "relative-humidity"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE: + return "ambient-temp"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE: + return "object-temp"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_VOLTAGE: + return "voltage"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_CURRENT: + return "current"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_COLOR: + return "color"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_RAW: + return "raw"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_PM10_STD: + return "pm10-std"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_PM25_STD: + return "pm25-std"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_PM100_STD: + return "pm100-std"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_PM10_ENV: + return "pm10-env"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_PM25_ENV: + return "pm25-env"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_PM100_ENV: + return "pm100-env"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_CO2: + return "co2"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_GAS_RESISTANCE: + return "gas-resistance"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_ALTITUDE: + return "altitude"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_LUX: + return "lux"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_ECO2: + return "eco2"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_UNITLESS_PERCENT: + return "unitless-percent"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT: + return "ambient-temp-fahrenheit"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE_FAHRENHEIT: + return "object-temp-fahrenheit"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_VOC_INDEX: + return "voc-index"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_NOX_INDEX: + return "nox-index"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_TVOC: + return "tvoc"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_BYTES: + return "bytes"; + case wippersnapper_sensor_SensorType_SENSOR_TYPE_BOOLEAN: + return "boolean"; + default: + return "unknown"; + } + } + protected: TwoWire *_i2c; ///< Pointer to the I2C bus bool _has_alt_i2c_bus; ///< True if the device is on an alternate I2C bus @@ -723,5 +858,9 @@ class drvBase { ulong _sensor_period; ///< The sensor's period, in milliseconds. ulong _sensor_period_prv; ///< The sensor's previous period, in milliseconds. size_t _sensors_count; ///< Number of sensors on the device. + wippersnapper_sensor_SensorType + _default_sensor_types[15]; ///< Default sensor types + size_t _default_sensor_types_count; ///< Number of default sensor types + const char *_sensor_type_strings[15]; ///< Sensor type strings }; #endif // DRV_BASE_H \ No newline at end of file diff --git a/src/components/i2c/drivers/drvBh1750.h b/src/components/i2c/drivers/drvBh1750.h index 2c2096dcc..98658c40f 100644 --- a/src/components/i2c/drivers/drvBh1750.h +++ b/src/components/i2c/drivers/drvBh1750.h @@ -96,6 +96,12 @@ class drvBh1750 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 1; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_LIGHT; + } + protected: hp_BH1750 *_bh1750; ///< Pointer to BH1750 light sensor object }; diff --git a/src/components/i2c/drivers/drvBme280.h b/src/components/i2c/drivers/drvBme280.h index d6b8f74f4..de5f6d378 100644 --- a/src/components/i2c/drivers/drvBme280.h +++ b/src/components/i2c/drivers/drvBme280.h @@ -137,6 +137,20 @@ class drvBme280 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 5; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY; + _default_sensor_types[3] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PRESSURE; + _default_sensor_types[4] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_ALTITUDE; + } + protected: Adafruit_BME280 *_bme; ///< BME280 object Adafruit_Sensor *_bme_temp = diff --git a/src/components/i2c/drivers/drvBme680.h b/src/components/i2c/drivers/drvBme680.h index 64c44793b..70b76e4be 100644 --- a/src/components/i2c/drivers/drvBme680.h +++ b/src/components/i2c/drivers/drvBme680.h @@ -178,6 +178,22 @@ class drvBme680 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 6; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY; + _default_sensor_types[3] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PRESSURE; + _default_sensor_types[4] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_ALTITUDE; + _default_sensor_types[5] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_GAS_RESISTANCE; + } + protected: Adafruit_BME680 *_bme; ///< BME680 object }; diff --git a/src/components/i2c/drivers/drvBmp280.h b/src/components/i2c/drivers/drvBmp280.h index 212f17029..ef06a846b 100644 --- a/src/components/i2c/drivers/drvBmp280.h +++ b/src/components/i2c/drivers/drvBmp280.h @@ -127,6 +127,18 @@ class drvBmp280 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 4; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PRESSURE; + _default_sensor_types[3] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_ALTITUDE; + } + protected: Adafruit_BMP280 *_bmp; ///< BMP280 object Adafruit_Sensor *_bmp_temp = diff --git a/src/components/i2c/drivers/drvBmp3xx.h b/src/components/i2c/drivers/drvBmp3xx.h index b23f436e7..c602dde4c 100644 --- a/src/components/i2c/drivers/drvBmp3xx.h +++ b/src/components/i2c/drivers/drvBmp3xx.h @@ -129,6 +129,18 @@ class drvBmp3xx : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 4; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PRESSURE; + _default_sensor_types[3] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_ALTITUDE; + } + protected: Adafruit_BMP3XX *_bmp3xx; ///< BMP3XX object }; diff --git a/src/components/i2c/drivers/drvDps310.h b/src/components/i2c/drivers/drvDps310.h index 0406d69b6..76499a010 100644 --- a/src/components/i2c/drivers/drvDps310.h +++ b/src/components/i2c/drivers/drvDps310.h @@ -151,6 +151,16 @@ class drvDps310 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 3; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PRESSURE; + } + protected: sensors_event_t _temp_event = { 0}; ///< DPS310 sensor event for temperature readings diff --git a/src/components/i2c/drivers/drvDs2484.h b/src/components/i2c/drivers/drvDs2484.h index 25fc26d21..7d3636eee 100644 --- a/src/components/i2c/drivers/drvDs2484.h +++ b/src/components/i2c/drivers/drvDs2484.h @@ -152,6 +152,14 @@ class drvDs2484 : public drvBase { return processTemperatureEvent(tempEvent); } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + } + protected: Adafruit_DS248x *_ds2484; ///< DS2484 driver object uint8_t _rom[8]; ///< DS18B20 ROM diff --git a/src/components/i2c/drivers/drvEns160.h b/src/components/i2c/drivers/drvEns160.h index 556031ad0..83bbdf663 100644 --- a/src/components/i2c/drivers/drvEns160.h +++ b/src/components/i2c/drivers/drvEns160.h @@ -133,6 +133,12 @@ class drvEns160 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = wippersnapper_sensor_SensorType_SENSOR_TYPE_RAW; + _default_sensor_types[1] = wippersnapper_sensor_SensorType_SENSOR_TYPE_TVOC; + } + protected: ScioSense_ENS160 *_ens160; ///< ENS160 object }; diff --git a/src/components/i2c/drivers/drvHts221.h b/src/components/i2c/drivers/drvHts221.h index d4a8c783e..05fefd419 100644 --- a/src/components/i2c/drivers/drvHts221.h +++ b/src/components/i2c/drivers/drvHts221.h @@ -99,6 +99,16 @@ class drvHts221 : public drvBase { return _hts221_humidity->getEvent(humidEvent); } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 3; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY; + } + protected: Adafruit_HTS221 *_hts221; ///< Pointer to an HTS221 object Adafruit_Sensor *_hts221_temp = diff --git a/src/components/i2c/drivers/drvHtu21d.h b/src/components/i2c/drivers/drvHtu21d.h index 12134f6ad..e5c6c19b6 100644 --- a/src/components/i2c/drivers/drvHtu21d.h +++ b/src/components/i2c/drivers/drvHtu21d.h @@ -86,6 +86,16 @@ class drvHtu21d : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 3; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY; + } + protected: Adafruit_HTU21DF *_htu21d; ///< Pointer to an HTU21D object }; diff --git a/src/components/i2c/drivers/drvIna219.h b/src/components/i2c/drivers/drvIna219.h index cf25a6be9..a5b866147 100644 --- a/src/components/i2c/drivers/drvIna219.h +++ b/src/components/i2c/drivers/drvIna219.h @@ -101,6 +101,14 @@ class drvIna219 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_VOLTAGE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_CURRENT; + } + protected: Adafruit_INA219 *_ina219; ///< Pointer to INA219 sensor object }; diff --git a/src/components/i2c/drivers/drvLc709203f.h b/src/components/i2c/drivers/drvLc709203f.h index 22286d35b..1cd432379 100644 --- a/src/components/i2c/drivers/drvLc709203f.h +++ b/src/components/i2c/drivers/drvLc709203f.h @@ -106,6 +106,14 @@ class drvLc709203f : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_VOLTAGE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_UNITLESS_PERCENT; + } + protected: Adafruit_LC709203F *_lc; ///< Pointer to LC709203F sensor object }; diff --git a/src/components/i2c/drivers/drvLps22hb.h b/src/components/i2c/drivers/drvLps22hb.h index 984843d06..2ade99ef1 100644 --- a/src/components/i2c/drivers/drvLps22hb.h +++ b/src/components/i2c/drivers/drvLps22hb.h @@ -104,6 +104,16 @@ class drvLps22hb : public drvBase { return _pressure->getEvent(pressureEvent); } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 3; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PRESSURE; + } + protected: Adafruit_LPS22 *_lps22; ///< LPS22HB object Adafruit_Sensor *_temp = diff --git a/src/components/i2c/drivers/drvLps25hb.h b/src/components/i2c/drivers/drvLps25hb.h index 54e77be9f..5df77131a 100644 --- a/src/components/i2c/drivers/drvLps25hb.h +++ b/src/components/i2c/drivers/drvLps25hb.h @@ -104,6 +104,16 @@ class drvLps25hb : public drvBase { return _pressure->getEvent(pressureEvent); } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 3; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PRESSURE; + } + protected: Adafruit_LPS25 *_lps25; ///< LPS25HB object Adafruit_Sensor *_temp = diff --git a/src/components/i2c/drivers/drvLtr329_Ltr303.h b/src/components/i2c/drivers/drvLtr329_Ltr303.h index 14711ef79..4e4d91f5f 100644 --- a/src/components/i2c/drivers/drvLtr329_Ltr303.h +++ b/src/components/i2c/drivers/drvLtr329_Ltr303.h @@ -115,6 +115,13 @@ class drvLtr329_Ltr303 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_LIGHT; + _default_sensor_types[1] = wippersnapper_sensor_SensorType_SENSOR_TYPE_RAW; + } + protected: Adafruit_LTR329 *_LTR329; ///< Pointer to LTR329 light sensor object diff --git a/src/components/i2c/drivers/drvLtr390.h b/src/components/i2c/drivers/drvLtr390.h index cdfa08eab..f725126a2 100644 --- a/src/components/i2c/drivers/drvLtr390.h +++ b/src/components/i2c/drivers/drvLtr390.h @@ -117,6 +117,13 @@ class drvLtr390 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_LIGHT; + _default_sensor_types[1] = wippersnapper_sensor_SensorType_SENSOR_TYPE_RAW; + } + protected: Adafruit_LTR390 *_ltr390; ///< Pointer to LTR390 light sensor object }; diff --git a/src/components/i2c/drivers/drvMCP9808.h b/src/components/i2c/drivers/drvMCP9808.h index 4b9d76ff7..df9ce1159 100644 --- a/src/components/i2c/drivers/drvMCP9808.h +++ b/src/components/i2c/drivers/drvMCP9808.h @@ -79,6 +79,14 @@ class drvMcp9808 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + } + protected: Adafruit_MCP9808 *_mcp9808; ///< Pointer to MCP9808 temperature sensor object }; diff --git a/src/components/i2c/drivers/drvMax1704x.h b/src/components/i2c/drivers/drvMax1704x.h index 7bdb93879..70c163496 100644 --- a/src/components/i2c/drivers/drvMax1704x.h +++ b/src/components/i2c/drivers/drvMax1704x.h @@ -93,6 +93,14 @@ class drvMax1704x : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_VOLTAGE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_UNITLESS_PERCENT; + } + protected: Adafruit_MAX17048 *_maxlipo; ///< Pointer to MAX17048 sensor object }; diff --git a/src/components/i2c/drivers/drvMcp3421.h b/src/components/i2c/drivers/drvMcp3421.h index a83921ae3..b46ddf41e 100644 --- a/src/components/i2c/drivers/drvMcp3421.h +++ b/src/components/i2c/drivers/drvMcp3421.h @@ -123,6 +123,15 @@ class drvMcp3421 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 3; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_VOLTAGE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_UNITLESS_PERCENT; + _default_sensor_types[2] = wippersnapper_sensor_SensorType_SENSOR_TYPE_RAW; + } + protected: Adafruit_MCP3421 *_mcp3421; ///< Pointer to MCP3421 sensor object }; diff --git a/src/components/i2c/drivers/drvMpl115a2.h b/src/components/i2c/drivers/drvMpl115a2.h index 6ada5ff9c..2c93e741b 100644 --- a/src/components/i2c/drivers/drvMpl115a2.h +++ b/src/components/i2c/drivers/drvMpl115a2.h @@ -94,6 +94,16 @@ class drvMpl115a2 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 3; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PRESSURE; + } + protected: Adafruit_MPL115A2 *_mpl115a2; ///< MPL115A2 object }; diff --git a/src/components/i2c/drivers/drvMprls.h b/src/components/i2c/drivers/drvMprls.h index 5bc38be4f..b5f642847 100644 --- a/src/components/i2c/drivers/drvMprls.h +++ b/src/components/i2c/drivers/drvMprls.h @@ -80,6 +80,12 @@ class drvMprls : public drvBase { return pressureEvent->pressure != NAN; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 1; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PRESSURE; + } + protected: Adafruit_MPRLS *_mprls; ///< MPRLS object }; diff --git a/src/components/i2c/drivers/drvMs8607.h b/src/components/i2c/drivers/drvMs8607.h index 708baf33a..00cdf57b6 100644 --- a/src/components/i2c/drivers/drvMs8607.h +++ b/src/components/i2c/drivers/drvMs8607.h @@ -121,6 +121,18 @@ class drvMs8607 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 4; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY; + _default_sensor_types[3] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PRESSURE; + } + protected: Adafruit_MS8607 *_ms8607; ///< MS8607 object Adafruit_Sensor *_ms8607_temp = diff --git a/src/components/i2c/drivers/drvNau7802.h b/src/components/i2c/drivers/drvNau7802.h index c08c526bc..f6542769a 100644 --- a/src/components/i2c/drivers/drvNau7802.h +++ b/src/components/i2c/drivers/drvNau7802.h @@ -138,6 +138,11 @@ class drvNau7802 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 1; + _default_sensor_types[0] = wippersnapper_sensor_SensorType_SENSOR_TYPE_RAW; + } + protected: Adafruit_NAU7802 *_nau7802 = nullptr; ///< NAU7802 object }; diff --git a/src/components/i2c/drivers/drvPct2075.h b/src/components/i2c/drivers/drvPct2075.h index 1eb11435a..e8a7b9187 100644 --- a/src/components/i2c/drivers/drvPct2075.h +++ b/src/components/i2c/drivers/drvPct2075.h @@ -79,6 +79,14 @@ class drvPct2075 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + } + protected: Adafruit_PCT2075 *_pct2075; ///< Pointer to PCT2075 temperature sensor object }; diff --git a/src/components/i2c/drivers/drvPm25.h b/src/components/i2c/drivers/drvPm25.h index 70bacab0c..9fd1353d4 100644 --- a/src/components/i2c/drivers/drvPm25.h +++ b/src/components/i2c/drivers/drvPm25.h @@ -125,6 +125,14 @@ class drvPm25 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + } + protected: Adafruit_PM25AQI *_pm25; ///< PM25 driver object }; diff --git a/src/components/i2c/drivers/drvScd30.h b/src/components/i2c/drivers/drvScd30.h index 977d11025..9bf6538d8 100644 --- a/src/components/i2c/drivers/drvScd30.h +++ b/src/components/i2c/drivers/drvScd30.h @@ -166,6 +166,17 @@ class drvScd30 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 4; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY; + _default_sensor_types[3] = wippersnapper_sensor_SensorType_SENSOR_TYPE_CO2; + } + protected: Adafruit_SCD30 *_scd = nullptr; ///< SCD30 driver object ulong _lastRead = 0; ///< Last time the sensor was read diff --git a/src/components/i2c/drivers/drvScd4x.h b/src/components/i2c/drivers/drvScd4x.h index c23bccadf..59f512efb 100644 --- a/src/components/i2c/drivers/drvScd4x.h +++ b/src/components/i2c/drivers/drvScd4x.h @@ -148,6 +148,17 @@ class drvScd4x : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 4; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY; + _default_sensor_types[3] = wippersnapper_sensor_SensorType_SENSOR_TYPE_CO2; + } + protected: SensirionI2cScd4x *_scd; ///< SCD4x driver object uint16_t _co2; ///< SCD4x co2 reading diff --git a/src/components/i2c/drivers/drvSen5x.h b/src/components/i2c/drivers/drvSen5x.h index c96a60604..e4a876a83 100644 --- a/src/components/i2c/drivers/drvSen5x.h +++ b/src/components/i2c/drivers/drvSen5x.h @@ -296,6 +296,16 @@ class drvSen5x : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 3; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PM10_STD; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PM25_STD; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PM100_STD; + } + protected: SensirionI2CSen5x *_sen; ///< SEN5X driver object }; diff --git a/src/components/i2c/drivers/drvSgp40.h b/src/components/i2c/drivers/drvSgp40.h index cae4c9de6..3cf7fcdca 100644 --- a/src/components/i2c/drivers/drvSgp40.h +++ b/src/components/i2c/drivers/drvSgp40.h @@ -91,6 +91,13 @@ class drvSgp40 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_VOC_INDEX; + _default_sensor_types[1] = wippersnapper_sensor_SensorType_SENSOR_TYPE_RAW; + } + protected: Adafruit_SGP40 *_sgp40; ///< SEN5X driver object }; diff --git a/src/components/i2c/drivers/drvSht3x.h b/src/components/i2c/drivers/drvSht3x.h index d2486a2f9..4f20651a3 100644 --- a/src/components/i2c/drivers/drvSht3x.h +++ b/src/components/i2c/drivers/drvSht3x.h @@ -68,6 +68,16 @@ class drvSht3x : public drvBase { return _sht3x->setAccuracy(SHTSensor::SHT_ACCURACY_HIGH); } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 3; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY; + } + /*******************************************************************************/ /*! @brief Gets the SHT3X's current temperature. diff --git a/src/components/i2c/drivers/drvSht4x.h b/src/components/i2c/drivers/drvSht4x.h index d53b94d4a..68802fff6 100644 --- a/src/components/i2c/drivers/drvSht4x.h +++ b/src/components/i2c/drivers/drvSht4x.h @@ -95,6 +95,16 @@ class drvSht4x : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 3; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY; + } + protected: Adafruit_SHT4x *_sht4x; ///< SHT4X object }; diff --git a/src/components/i2c/drivers/drvShtc3.h b/src/components/i2c/drivers/drvShtc3.h index ec633d7ea..28b866c93 100644 --- a/src/components/i2c/drivers/drvShtc3.h +++ b/src/components/i2c/drivers/drvShtc3.h @@ -94,6 +94,16 @@ class drvShtc3 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 3; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY; + } + protected: SHTSensor *_shtc3; ///< SHTC3 object }; diff --git a/src/components/i2c/drivers/drvSi7021.h b/src/components/i2c/drivers/drvSi7021.h index d9737e354..2db0e244d 100644 --- a/src/components/i2c/drivers/drvSi7021.h +++ b/src/components/i2c/drivers/drvSi7021.h @@ -99,6 +99,16 @@ class drvSi7021 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 3; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY; + } + protected: Adafruit_Si7021 *_si7021; ///< SI7021 driver object }; diff --git a/src/components/i2c/drivers/drvStemmaSoil.h b/src/components/i2c/drivers/drvStemmaSoil.h index bda0dd9f4..3f6555626 100644 --- a/src/components/i2c/drivers/drvStemmaSoil.h +++ b/src/components/i2c/drivers/drvStemmaSoil.h @@ -103,6 +103,15 @@ class drvStemmaSoil : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 3; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + _default_sensor_types[2] = wippersnapper_sensor_SensorType_SENSOR_TYPE_RAW; + } + protected: Adafruit_seesaw *_seesaw = nullptr; ///< Seesaw object }; diff --git a/src/components/i2c/drivers/drvTmp117.h b/src/components/i2c/drivers/drvTmp117.h index 38db6d6b6..1302fffff 100644 --- a/src/components/i2c/drivers/drvTmp117.h +++ b/src/components/i2c/drivers/drvTmp117.h @@ -78,6 +78,14 @@ class drvTmp117 : public drvBase { return _tmp117->getEvent(tempEvent); } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT; + } + protected: Adafruit_TMP117 *_tmp117; ///< Pointer to TMP117 temperature sensor object }; diff --git a/src/components/i2c/drivers/drvTsl2591.h b/src/components/i2c/drivers/drvTsl2591.h index 0aea6c4c6..12cd33acc 100644 --- a/src/components/i2c/drivers/drvTsl2591.h +++ b/src/components/i2c/drivers/drvTsl2591.h @@ -95,6 +95,12 @@ class drvTsl2591 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 1; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_LIGHT; + } + protected: Adafruit_TSL2591 *_tsl; ///< Pointer to TSL2591 light sensor object }; diff --git a/src/components/i2c/drivers/drvVeml7700.h b/src/components/i2c/drivers/drvVeml7700.h index 6262a9744..f23d56883 100644 --- a/src/components/i2c/drivers/drvVeml7700.h +++ b/src/components/i2c/drivers/drvVeml7700.h @@ -77,10 +77,15 @@ class drvVeml7700 : public drvBase { bool getEventLight(sensors_event_t *lightEvent) { // Get sensor event populated in lux via AUTO integration and gain lightEvent->light = _veml->readLux(VEML_LUX_AUTO); - return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 1; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_LIGHT; + } + protected: Adafruit_VEML7700 *_veml; ///< Pointer to VEML7700 light sensor object }; diff --git a/src/components/i2c/drivers/drvVl53l0x.h b/src/components/i2c/drivers/drvVl53l0x.h index 70e32c876..a9f05a360 100644 --- a/src/components/i2c/drivers/drvVl53l0x.h +++ b/src/components/i2c/drivers/drvVl53l0x.h @@ -88,6 +88,12 @@ class drvVl53l0x : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 1; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PROXIMITY; + } + protected: Adafruit_VL53L0X *_vl53l0x; ///< Pointer to VL53L0X temperature sensor object }; diff --git a/src/components/i2c/drivers/drvVl53l1x.h b/src/components/i2c/drivers/drvVl53l1x.h index 1c4357c68..2896687f4 100644 --- a/src/components/i2c/drivers/drvVl53l1x.h +++ b/src/components/i2c/drivers/drvVl53l1x.h @@ -94,6 +94,12 @@ class drvVl53l1x : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 1; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PROXIMITY; + } + protected: Adafruit_VL53L1X *_VL53L1X; ///< Pointer to VL53L1X temperature sensor object }; diff --git a/src/components/i2c/drivers/drvVl53l4cd.h b/src/components/i2c/drivers/drvVl53l4cd.h index b324eeae5..523f16708 100644 --- a/src/components/i2c/drivers/drvVl53l4cd.h +++ b/src/components/i2c/drivers/drvVl53l4cd.h @@ -161,6 +161,12 @@ class drvVl53l4cd : public drvBase { return false; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 1; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PROXIMITY; + } + protected: VL53L4CD *_VL53L4CD; ///< Pointer to VL53L4CD temperature sensor object }; diff --git a/src/components/i2c/drivers/drvVl53l4cx.h b/src/components/i2c/drivers/drvVl53l4cx.h index 79707d3bb..13c2ec6e4 100644 --- a/src/components/i2c/drivers/drvVl53l4cx.h +++ b/src/components/i2c/drivers/drvVl53l4cx.h @@ -202,6 +202,13 @@ class drvVl53l4cx : public drvBase { return false; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PROXIMITY; + _default_sensor_types[0] = wippersnapper_sensor_SensorType_SENSOR_TYPE_RAW; + } + protected: VL53L4CX *_VL53L4CX; ///< Pointer to VL53L4CX temperature sensor object }; diff --git a/src/components/i2c/drivers/drvVl6180x.h b/src/components/i2c/drivers/drvVl6180x.h index 325a70377..2a1dd698f 100644 --- a/src/components/i2c/drivers/drvVl6180x.h +++ b/src/components/i2c/drivers/drvVl6180x.h @@ -127,6 +127,14 @@ class drvVl6180x : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PROXIMITY; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_LIGHT; + } + protected: Adafruit_VL6180X *_vl6180x; ///< Pointer to VL6180X temperature sensor object }; diff --git a/src/components/i2c/drivers/drvVncl4020.h b/src/components/i2c/drivers/drvVncl4020.h index 5b8183f96..ccaaa66a8 100644 --- a/src/components/i2c/drivers/drvVncl4020.h +++ b/src/components/i2c/drivers/drvVncl4020.h @@ -93,6 +93,14 @@ class drvVncl4020 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_LIGHT; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PROXIMITY; + } + protected: Adafruit_VCNL4020 *_vcnl4020; ///< Pointer to VCNL4020 light sensor object }; diff --git a/src/components/i2c/drivers/drvVncl4040.h b/src/components/i2c/drivers/drvVncl4040.h index 2d83f2931..04de5ff40 100644 --- a/src/components/i2c/drivers/drvVncl4040.h +++ b/src/components/i2c/drivers/drvVncl4040.h @@ -107,6 +107,14 @@ class drvVncl4040 : public drvBase { return true; } + void ConfigureDefaultSensorTypes() override { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_LIGHT; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_PROXIMITY; + } + protected: Adafruit_VCNL4040 *_vcnl4040; ///< Pointer to VCNL4040 light sensor object }; diff --git a/src/components/i2c/hardware.cpp b/src/components/i2c/hardware.cpp index d3bd8901c..ec7e821d0 100644 --- a/src/components/i2c/hardware.cpp +++ b/src/components/i2c/hardware.cpp @@ -145,6 +145,69 @@ void I2cHardware::InitBus(bool is_default, const char *sda, const char *scl) { /***********************************************************************/ TwoWire *I2cHardware::GetBus() { return _bus; } +/***********************************************************************/ +/*! + @brief Scans the I2C bus for devices. + @param scan_results + The results of the I2C bus scan. + @returns True if the bus was successfully scanned, False otherwise. +*/ +/***********************************************************************/ +bool I2cHardware::ScanBus(wippersnapper_i2c_I2cBusScanned *scan_results) { + if (!scan_results) + return false; + + if (!_bus) { + WS_DEBUG_PRINTLN("[i2c] ERROR: I2C bus not initialized!"); + return false; + } + + // Perform a bus scan + WS_DEBUG_PRINTLN("[i2c]: Scanning I2C Bus for Devices..."); + for (uint8_t address = 1; address < 127; address++) { + _bus->beginTransmission(address); + uint8_t endTransmissionRC = _bus->endTransmission(); + + if (endTransmissionRC == 0) { + WS_DEBUG_PRINT("[i2c] Found Device at "); + WS_DEBUG_PRINT("0x"); + WS_DEBUG_PRINTLN(address, HEX); + scan_results + ->i2c_bus_found_devices[scan_results->i2c_bus_found_devices_count] + .i2c_device_address = address; + scan_results->i2c_bus_found_devices_count++; + } +#if defined(ARDUINO_ARCH_ESP32) + // Check endTransmission()'s return code (Arduino-ESP32 ONLY) + else if (endTransmissionRC == 3) { + WS_DEBUG_PRINTLN("[i2c] Did not find device: NACK on transmit of data!"); + continue; + } else if (endTransmissionRC == 2) { + // WS_DEBUG_PRINTLN("[i2c] Did not find device: NACK on transmit of + // address!"); + continue; + } else if (endTransmissionRC == 1) { + WS_DEBUG_PRINTLN( + "[i2c] Did not find device: data too long to fit in xmit buffer!"); + continue; + } else if (endTransmissionRC == 4) { + WS_DEBUG_PRINTLN( + "[i2c] Did not find device: Unspecified bus error occured!"); + continue; + } else if (endTransmissionRC == 5) { + WS_DEBUG_PRINTLN("[i2c] Did not find device: Bus timed out!"); + continue; + } +#endif // ARDUINO_ARCH_ESP32 + else { + // Did not find a device, keep scanning + continue; + } + } + + return true; +} + /***********************************************************************/ /*! @brief Adds a MUX to the I2C bus. @@ -165,7 +228,7 @@ bool I2cHardware::AddMuxToBus(uint32_t address_register, const char *name) { return false; } - _mux_address_register = address_register; + _mux_address = address_register; _has_mux = true; // Put MUX in back into its default state cuz we don't know if we're about to // use it again @@ -181,7 +244,8 @@ bool I2cHardware::AddMuxToBus(uint32_t address_register, const char *name) { void I2cHardware::ClearMuxChannel() { if (!_has_mux) return; - _bus->beginTransmission(_mux_address_register); + + _bus->beginTransmission(_mux_address); if (_mux_max_channels == 4) _bus->write(0b0000); else if (_mux_max_channels == 8) @@ -199,7 +263,8 @@ void I2cHardware::ClearMuxChannel() { void I2cHardware::SelectMuxChannel(uint32_t channel) { if (channel > _mux_max_channels - 1) return; - _bus->beginTransmission(_mux_address_register); + + _bus->beginTransmission(_mux_address); _bus->write(1 << channel); _bus->endTransmission(); } diff --git a/src/components/i2c/hardware.h b/src/components/i2c/hardware.h index ea5c063cd..f0136254e 100644 --- a/src/components/i2c/hardware.h +++ b/src/components/i2c/hardware.h @@ -35,6 +35,7 @@ class I2cHardware { const char *scl = nullptr); TwoWire *GetBus(); wippersnapper_i2c_I2cBusStatus GetBusStatus(); + bool ScanBus(wippersnapper_i2c_I2cBusScanned *scan_results); // MUX bool AddMuxToBus(uint32_t address_register, const char *name); void SelectMuxChannel(uint32_t channel); @@ -46,7 +47,9 @@ class I2cHardware { wippersnapper_i2c_I2cBusStatus _bus_status; ///< I2C bus status TwoWire *_bus = nullptr; ///< I2C bus bool _has_mux; ///< Is a MUX present on the bus? - uint32_t _mux_address_register; ///< I2C address for the MUX + uint32_t _mux_address; ///< I2C address for the MUX int _mux_max_channels; ///< Maximum possible number of MUX channels + char *_sda; ///< SDA pin + char *_scl; ///< SCL pin }; #endif // WS_I2C_HARDWARE_H \ No newline at end of file diff --git a/src/components/i2c/model.cpp b/src/components/i2c/model.cpp index 9f7837577..c28a667ca 100644 --- a/src/components/i2c/model.cpp +++ b/src/components/i2c/model.cpp @@ -21,7 +21,7 @@ /***********************************************************************/ I2cModel::I2cModel() { _msg_i2c_bus_scan = wippersnapper_i2c_I2cBusScan_init_default; - _msg_i2c_bus_scanned = wippersnapper_i2c_I2cBusScan_init_default; + _msg_i2c_bus_scanned = wippersnapper_i2c_I2cBusScanned_init_default; _msg_i2c_device_add_replace = wippersnapper_i2c_I2cDeviceAddOrReplace_init_default; _msg_i2c_device_added_replaced = diff --git a/src/display/ws_display_driver.cpp b/src/display/ws_display_driver.cpp index c3b8dbe09..a901b1954 100644 --- a/src/display/ws_display_driver.cpp +++ b/src/display/ws_display_driver.cpp @@ -20,7 +20,7 @@ @brief Creates a new WipperSnapper display driver object from a configuration struct. @param config - Configuration struct., from FS.parseDisplayConfig(); + Configuration struct., from FS.ParseFileDisplayCfg(); */ /**************************************************************************/ ws_display_driver::ws_display_driver(displayConfig config) { diff --git a/src/protos/i2c.pb.c b/src/protos/i2c.pb.c index 6428602ee..88655b887 100644 --- a/src/protos/i2c.pb.c +++ b/src/protos/i2c.pb.c @@ -9,6 +9,9 @@ PB_BIND(wippersnapper_i2c_I2cDeviceDescriptor, wippersnapper_i2c_I2cDeviceDescriptor, AUTO) +PB_BIND(wippersnapper_i2c_I2cBusDescriptor, wippersnapper_i2c_I2cBusDescriptor, AUTO) + + PB_BIND(wippersnapper_i2c_I2cBusScan, wippersnapper_i2c_I2cBusScan, AUTO) diff --git a/src/protos/i2c.pb.h b/src/protos/i2c.pb.h index 826621304..8d410131d 100644 --- a/src/protos/i2c.pb.h +++ b/src/protos/i2c.pb.h @@ -45,9 +45,21 @@ typedef struct _wippersnapper_i2c_I2cDeviceDescriptor { } wippersnapper_i2c_I2cDeviceDescriptor; /* * - I2cBusScan represents a command for a device to perform an i2c scan. It is an empty message. */ + I2cBusDescriptor represents the I2c bus' SDA and SCL pins. */ +typedef struct _wippersnapper_i2c_I2cBusDescriptor { + char i2c_bus_sda[15]; /* * SDA pin for an i2c bus.* */ + char i2c_bus_scl[15]; /* * SCL pin for an i2c bus.* */ +} wippersnapper_i2c_I2cBusDescriptor; + +/* * + I2cBusScan represents a command for a device to perform an i2c scan. */ typedef struct _wippersnapper_i2c_I2cBusScan { - char dummy_field; + bool scan_default_bus; /* * Default - Scan for i2c devices on the hardware's default I2C bus.* */ + bool scan_alt_bus; /* * Optional - Scan for i2c devices on an alternative I2C bus.* */ + bool has_i2c_alt_bus_descriptor; + wippersnapper_i2c_I2cBusDescriptor i2c_alt_bus_descriptor; /* * Optional - Metadata to optionally initialize (if not already init'd) an alt. i2c bus.* */ + bool scan_default_bus_mux; /* * Optional - Scan for i2c devices on the default I2C bus with a multiplexer.* */ + bool scan_alt_bus_mux; /* * Optional - Scan for i2c devices on an alternative I2C bus with a multiplexer.* */ } wippersnapper_i2c_I2cBusScan; /* * @@ -69,6 +81,7 @@ typedef struct _wippersnapper_i2c_I2cDeviceAddOrReplace { float i2c_device_period; /* * The desired period to update the I2c device's sensor(s), in seconds. */ pb_size_t i2c_device_sensor_types_count; wippersnapper_sensor_SensorType i2c_device_sensor_types[15]; /* * SI Types for each sensor on the I2c device. */ + bool is_persistent; /* * Offline-Mode ONLY - True if the device exits in the config file, False otherwise. * */ } wippersnapper_i2c_I2cDeviceAddOrReplace; /* * @@ -92,8 +105,7 @@ typedef struct _wippersnapper_i2c_I2cDeviceRemove { typedef struct _wippersnapper_i2c_I2cDeviceRemoved { bool has_i2c_device_description; wippersnapper_i2c_I2cDeviceDescriptor i2c_device_description; /* * The I2c device's address and metadata. */ - wippersnapper_i2c_I2cBusStatus i2c_bus_status; /* * The I2c bus' status. * */ - wippersnapper_i2c_I2cDeviceStatus i2c_device_status; /* * The I2c device's status. * */ + bool did_remove; /* * True if the I2C device was successfully removed from the controller, False otherwise. * */ } wippersnapper_i2c_I2cDeviceRemoved; /* * @@ -123,6 +135,7 @@ extern "C" { + #define wippersnapper_i2c_I2cBusScanned_i2c_bus_status_ENUMTYPE wippersnapper_i2c_I2cBusStatus #define wippersnapper_i2c_I2cDeviceAddOrReplace_i2c_device_sensor_types_ENUMTYPE wippersnapper_sensor_SensorType @@ -131,27 +144,27 @@ extern "C" { #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_i2c_device_status_ENUMTYPE wippersnapper_i2c_I2cDeviceStatus -#define wippersnapper_i2c_I2cDeviceRemoved_i2c_bus_status_ENUMTYPE wippersnapper_i2c_I2cBusStatus -#define wippersnapper_i2c_I2cDeviceRemoved_i2c_device_status_ENUMTYPE wippersnapper_i2c_I2cDeviceStatus /* Initializer values for message structs */ #define wippersnapper_i2c_I2cDeviceDescriptor_init_default {"", "", 0, 0, 0} -#define wippersnapper_i2c_I2cBusScan_init_default {0} +#define wippersnapper_i2c_I2cBusDescriptor_init_default {"", ""} +#define wippersnapper_i2c_I2cBusScan_init_default {0, 0, false, wippersnapper_i2c_I2cBusDescriptor_init_default, 0, 0} #define wippersnapper_i2c_I2cBusScanned_init_default {0, {wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default}, _wippersnapper_i2c_I2cBusStatus_MIN} -#define wippersnapper_i2c_I2cDeviceAddOrReplace_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default, "", 0, 0, {_wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN}} +#define wippersnapper_i2c_I2cDeviceAddOrReplace_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default, "", 0, 0, {_wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN}, 0} #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default, _wippersnapper_i2c_I2cBusStatus_MIN, _wippersnapper_i2c_I2cDeviceStatus_MIN} #define wippersnapper_i2c_I2cDeviceRemove_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default} -#define wippersnapper_i2c_I2cDeviceRemoved_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default, _wippersnapper_i2c_I2cBusStatus_MIN, _wippersnapper_i2c_I2cDeviceStatus_MIN} +#define wippersnapper_i2c_I2cDeviceRemoved_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default, 0} #define wippersnapper_i2c_I2cDeviceEvent_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default, 0, {wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default}} #define wippersnapper_i2c_I2cDeviceDescriptor_init_zero {"", "", 0, 0, 0} -#define wippersnapper_i2c_I2cBusScan_init_zero {0} +#define wippersnapper_i2c_I2cBusDescriptor_init_zero {"", ""} +#define wippersnapper_i2c_I2cBusScan_init_zero {0, 0, false, wippersnapper_i2c_I2cBusDescriptor_init_zero, 0, 0} #define wippersnapper_i2c_I2cBusScanned_init_zero {0, {wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero}, _wippersnapper_i2c_I2cBusStatus_MIN} -#define wippersnapper_i2c_I2cDeviceAddOrReplace_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, "", 0, 0, {_wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN}} +#define wippersnapper_i2c_I2cDeviceAddOrReplace_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, "", 0, 0, {_wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN}, 0} #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, _wippersnapper_i2c_I2cBusStatus_MIN, _wippersnapper_i2c_I2cDeviceStatus_MIN} #define wippersnapper_i2c_I2cDeviceRemove_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero} -#define wippersnapper_i2c_I2cDeviceRemoved_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, _wippersnapper_i2c_I2cBusStatus_MIN, _wippersnapper_i2c_I2cDeviceStatus_MIN} +#define wippersnapper_i2c_I2cDeviceRemoved_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, 0} #define wippersnapper_i2c_I2cDeviceEvent_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, 0, {wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero}} /* Field tags (for use in manual encoding/decoding) */ @@ -160,19 +173,26 @@ extern "C" { #define wippersnapper_i2c_I2cDeviceDescriptor_i2c_device_address_tag 3 #define wippersnapper_i2c_I2cDeviceDescriptor_i2c_mux_address_tag 4 #define wippersnapper_i2c_I2cDeviceDescriptor_i2c_mux_channel_tag 5 +#define wippersnapper_i2c_I2cBusDescriptor_i2c_bus_sda_tag 1 +#define wippersnapper_i2c_I2cBusDescriptor_i2c_bus_scl_tag 2 +#define wippersnapper_i2c_I2cBusScan_scan_default_bus_tag 1 +#define wippersnapper_i2c_I2cBusScan_scan_alt_bus_tag 2 +#define wippersnapper_i2c_I2cBusScan_i2c_alt_bus_descriptor_tag 3 +#define wippersnapper_i2c_I2cBusScan_scan_default_bus_mux_tag 4 +#define wippersnapper_i2c_I2cBusScan_scan_alt_bus_mux_tag 5 #define wippersnapper_i2c_I2cBusScanned_i2c_bus_found_devices_tag 1 #define wippersnapper_i2c_I2cBusScanned_i2c_bus_status_tag 2 #define wippersnapper_i2c_I2cDeviceAddOrReplace_i2c_device_description_tag 1 #define wippersnapper_i2c_I2cDeviceAddOrReplace_i2c_device_name_tag 2 #define wippersnapper_i2c_I2cDeviceAddOrReplace_i2c_device_period_tag 3 #define wippersnapper_i2c_I2cDeviceAddOrReplace_i2c_device_sensor_types_tag 4 +#define wippersnapper_i2c_I2cDeviceAddOrReplace_is_persistent_tag 5 #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_i2c_device_description_tag 1 #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_i2c_bus_status_tag 2 #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_i2c_device_status_tag 3 #define wippersnapper_i2c_I2cDeviceRemove_i2c_device_description_tag 1 #define wippersnapper_i2c_I2cDeviceRemoved_i2c_device_description_tag 1 -#define wippersnapper_i2c_I2cDeviceRemoved_i2c_bus_status_tag 2 -#define wippersnapper_i2c_I2cDeviceRemoved_i2c_device_status_tag 3 +#define wippersnapper_i2c_I2cDeviceRemoved_did_remove_tag 2 #define wippersnapper_i2c_I2cDeviceEvent_i2c_device_description_tag 1 #define wippersnapper_i2c_I2cDeviceEvent_i2c_device_events_tag 2 @@ -186,10 +206,21 @@ X(a, STATIC, SINGULAR, UINT32, i2c_mux_channel, 5) #define wippersnapper_i2c_I2cDeviceDescriptor_CALLBACK NULL #define wippersnapper_i2c_I2cDeviceDescriptor_DEFAULT NULL -#define wippersnapper_i2c_I2cBusScan_FIELDLIST(X, a) \ +#define wippersnapper_i2c_I2cBusDescriptor_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, STRING, i2c_bus_sda, 1) \ +X(a, STATIC, SINGULAR, STRING, i2c_bus_scl, 2) +#define wippersnapper_i2c_I2cBusDescriptor_CALLBACK NULL +#define wippersnapper_i2c_I2cBusDescriptor_DEFAULT NULL +#define wippersnapper_i2c_I2cBusScan_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, BOOL, scan_default_bus, 1) \ +X(a, STATIC, SINGULAR, BOOL, scan_alt_bus, 2) \ +X(a, STATIC, OPTIONAL, MESSAGE, i2c_alt_bus_descriptor, 3) \ +X(a, STATIC, SINGULAR, BOOL, scan_default_bus_mux, 4) \ +X(a, STATIC, SINGULAR, BOOL, scan_alt_bus_mux, 5) #define wippersnapper_i2c_I2cBusScan_CALLBACK NULL #define wippersnapper_i2c_I2cBusScan_DEFAULT NULL +#define wippersnapper_i2c_I2cBusScan_i2c_alt_bus_descriptor_MSGTYPE wippersnapper_i2c_I2cBusDescriptor #define wippersnapper_i2c_I2cBusScanned_FIELDLIST(X, a) \ X(a, STATIC, REPEATED, MESSAGE, i2c_bus_found_devices, 1) \ @@ -202,7 +233,8 @@ X(a, STATIC, SINGULAR, UENUM, i2c_bus_status, 2) X(a, STATIC, OPTIONAL, MESSAGE, i2c_device_description, 1) \ X(a, STATIC, SINGULAR, STRING, i2c_device_name, 2) \ X(a, STATIC, SINGULAR, FLOAT, i2c_device_period, 3) \ -X(a, STATIC, REPEATED, UENUM, i2c_device_sensor_types, 4) +X(a, STATIC, REPEATED, UENUM, i2c_device_sensor_types, 4) \ +X(a, STATIC, SINGULAR, BOOL, is_persistent, 5) #define wippersnapper_i2c_I2cDeviceAddOrReplace_CALLBACK NULL #define wippersnapper_i2c_I2cDeviceAddOrReplace_DEFAULT NULL #define wippersnapper_i2c_I2cDeviceAddOrReplace_i2c_device_description_MSGTYPE wippersnapper_i2c_I2cDeviceDescriptor @@ -223,8 +255,7 @@ X(a, STATIC, OPTIONAL, MESSAGE, i2c_device_description, 1) #define wippersnapper_i2c_I2cDeviceRemoved_FIELDLIST(X, a) \ X(a, STATIC, OPTIONAL, MESSAGE, i2c_device_description, 1) \ -X(a, STATIC, SINGULAR, UENUM, i2c_bus_status, 2) \ -X(a, STATIC, SINGULAR, UENUM, i2c_device_status, 3) +X(a, STATIC, SINGULAR, BOOL, did_remove, 2) #define wippersnapper_i2c_I2cDeviceRemoved_CALLBACK NULL #define wippersnapper_i2c_I2cDeviceRemoved_DEFAULT NULL #define wippersnapper_i2c_I2cDeviceRemoved_i2c_device_description_MSGTYPE wippersnapper_i2c_I2cDeviceDescriptor @@ -238,6 +269,7 @@ X(a, STATIC, REPEATED, MESSAGE, i2c_device_events, 2) #define wippersnapper_i2c_I2cDeviceEvent_i2c_device_events_MSGTYPE wippersnapper_sensor_SensorEvent extern const pb_msgdesc_t wippersnapper_i2c_I2cDeviceDescriptor_msg; +extern const pb_msgdesc_t wippersnapper_i2c_I2cBusDescriptor_msg; extern const pb_msgdesc_t wippersnapper_i2c_I2cBusScan_msg; extern const pb_msgdesc_t wippersnapper_i2c_I2cBusScanned_msg; extern const pb_msgdesc_t wippersnapper_i2c_I2cDeviceAddOrReplace_msg; @@ -248,6 +280,7 @@ extern const pb_msgdesc_t wippersnapper_i2c_I2cDeviceEvent_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define wippersnapper_i2c_I2cDeviceDescriptor_fields &wippersnapper_i2c_I2cDeviceDescriptor_msg +#define wippersnapper_i2c_I2cBusDescriptor_fields &wippersnapper_i2c_I2cBusDescriptor_msg #define wippersnapper_i2c_I2cBusScan_fields &wippersnapper_i2c_I2cBusScan_msg #define wippersnapper_i2c_I2cBusScanned_fields &wippersnapper_i2c_I2cBusScanned_msg #define wippersnapper_i2c_I2cDeviceAddOrReplace_fields &wippersnapper_i2c_I2cDeviceAddOrReplace_msg @@ -258,13 +291,14 @@ extern const pb_msgdesc_t wippersnapper_i2c_I2cDeviceEvent_msg; /* Maximum encoded size of messages (where known) */ #define WIPPERSNAPPER_I2C_I2C_PB_H_MAX_SIZE wippersnapper_i2c_I2cBusScanned_size -#define wippersnapper_i2c_I2cBusScan_size 0 +#define wippersnapper_i2c_I2cBusDescriptor_size 32 +#define wippersnapper_i2c_I2cBusScan_size 42 #define wippersnapper_i2c_I2cBusScanned_size 6242 -#define wippersnapper_i2c_I2cDeviceAddOrReplace_size 103 +#define wippersnapper_i2c_I2cDeviceAddOrReplace_size 105 #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_size 56 #define wippersnapper_i2c_I2cDeviceDescriptor_size 50 #define wippersnapper_i2c_I2cDeviceRemove_size 52 -#define wippersnapper_i2c_I2cDeviceRemoved_size 56 +#define wippersnapper_i2c_I2cDeviceRemoved_size 54 #if defined(wippersnapper_sensor_SensorEvent_size) #define wippersnapper_i2c_I2cDeviceEvent_size (142 + 15*wippersnapper_sensor_SensorEvent_size) #endif diff --git a/src/protos/signal.pb.h b/src/protos/signal.pb.h index 3262a6c05..1f187c687 100644 --- a/src/protos/signal.pb.h +++ b/src/protos/signal.pb.h @@ -252,7 +252,7 @@ extern const pb_msgdesc_t wippersnapper_signal_DeviceToBroker_msg; /* Maximum encoded size of messages (where known) */ #if defined(wippersnapper_digitalio_DigitalIOEvent_size) && defined(wippersnapper_digitalio_DigitalIOWrite_size) && defined(wippersnapper_uart_UARTAdd_size) && defined(wippersnapper_uart_UARTRemove_size) -union wippersnapper_signal_BrokerToDevice_payload_size_union {char f12[(6 + wippersnapper_digitalio_DigitalIOEvent_size)]; char f13[(6 + wippersnapper_digitalio_DigitalIOWrite_size)]; char f80[(7 + wippersnapper_uart_UARTAdd_size)]; char f81[(7 + wippersnapper_uart_UARTRemove_size)]; char f0[106];}; +union wippersnapper_signal_BrokerToDevice_payload_size_union {char f12[(6 + wippersnapper_digitalio_DigitalIOEvent_size)]; char f13[(6 + wippersnapper_digitalio_DigitalIOWrite_size)]; char f80[(7 + wippersnapper_uart_UARTAdd_size)]; char f81[(7 + wippersnapper_uart_UARTRemove_size)]; char f0[108];}; #endif #if defined(wippersnapper_digitalio_DigitalIOEvent_size) && defined(wippersnapper_analogio_AnalogIOEvent_size) && defined(wippersnapper_ds18x20_Ds18x20Event_size) && defined(wippersnapper_uart_UARTAdded_size) && defined(wippersnapper_uart_UARTEvent_size) && defined(wippersnapper_i2c_I2cDeviceEvent_size) union wippersnapper_signal_DeviceToBroker_payload_size_union {char f10[(6 + wippersnapper_digitalio_DigitalIOEvent_size)]; char f20[(7 + wippersnapper_analogio_AnalogIOEvent_size)]; char f80[(7 + wippersnapper_ds18x20_Ds18x20Event_size)]; char f90[(7 + wippersnapper_uart_UARTAdded_size)]; char f100[(7 + wippersnapper_uart_UARTEvent_size)]; char f113[(7 + wippersnapper_i2c_I2cDeviceEvent_size)]; char f0[6246];}; diff --git a/src/provisioning/littlefs/WipperSnapper_LittleFS.cpp b/src/provisioning/littlefs/WipperSnapper_LittleFS.cpp index 697614180..bdfcfa4bb 100644 --- a/src/provisioning/littlefs/WipperSnapper_LittleFS.cpp +++ b/src/provisioning/littlefs/WipperSnapper_LittleFS.cpp @@ -30,8 +30,8 @@ WipperSnapper_LittleFS::WipperSnapper_LittleFS() { // Attempt to initialize filesystem if (!LittleFS.begin()) { - fsHalt("ERROR: Failure initializing LittleFS!", - WS_LED_STATUS_WAITING_FOR_REG_MSG); + HaltFilesystem("ERROR: Failure initializing LittleFS!", + WS_LED_STATUS_WAITING_FOR_REG_MSG); } } @@ -48,25 +48,26 @@ WipperSnapper_LittleFS::~WipperSnapper_LittleFS() { LittleFS.end(); } on the LittleFS filesystem. */ /**************************************************************************/ -void WipperSnapper_LittleFS::parseSecrets() { +void WipperSnapper_LittleFS::ParseFileSecrets() { // Check if `secrets.json` file exists on FS if (!LittleFS.exists("/secrets.json")) { - fsHalt("ERROR: No secrets.json found on filesystem - did you upload " - "credentials?"); + HaltFilesystem( + "ERROR: No secrets.json found on filesystem - did you upload " + "credentials?"); } // Attempt to open secrets.json file for reading File secretsFile = LittleFS.open("/secrets.json", "r"); if (!secretsFile) { - fsHalt("ERROR: Could not open secrets.json file for reading!"); + HaltFilesystem("ERROR: Could not open secrets.json file for reading!"); } // Attempt to deserialize the file's JSON document JsonDocument doc; DeserializationError error = deserializeJson(doc, secretsFile); if (error) { - fsHalt(String("ERROR: deserializeJson() failed with code ") + - error.c_str()); + HaltFilesystem(String("ERROR: deserializeJson() failed with code ") + + error.c_str()); } if (doc.containsKey("network_type_wifi")) { // set default network config @@ -86,8 +87,9 @@ void WipperSnapper_LittleFS::parseSecrets() { WS_DEBUG_PRINT("Network count: "); WS_DEBUG_PRINTLN(altNetworkCount); if (altNetworkCount == 0) { - fsHalt("ERROR: No alternative network entries found under " - "network_type_wifi.alternative_networks in secrets.json!"); + HaltFilesystem( + "ERROR: No alternative network entries found under " + "network_type_wifi.alternative_networks in secrets.json!"); } // check if over 3, warn user and take first three for (int i = 0; i < altNetworkCount; i++) { @@ -105,11 +107,11 @@ void WipperSnapper_LittleFS::parseSecrets() { } WsV2._isWiFiMultiV2 = true; } else { - fsHalt("ERROR: Unrecognised value type for " - "network_type_wifi.alternative_networks in secrets.json!"); + HaltFilesystem("ERROR: Unrecognised value type for " + "network_type_wifi.alternative_networks in secrets.json!"); } } else { - fsHalt("ERROR: Could not find network_type_wifi in secrets.json!"); + HaltFilesystem("ERROR: Could not find network_type_wifi in secrets.json!"); } // Extract a config struct from the JSON document @@ -118,16 +120,17 @@ void WipperSnapper_LittleFS::parseSecrets() { // Validate the config struct is not filled with default values if (strcmp(WsV2._configV2.aio_user, "YOUR_IO_USERNAME_HERE") == 0 || strcmp(WsV2._configV2.aio_key, "YOUR_IO_KEY_HERE") == 0) { - fsHalt( + HaltFilesystem( "ERROR: Invalid IO credentials in secrets.json! TO FIX: Please change " "io_username and io_key to match your Adafruit IO credentials!\n"); } if (strcmp(WsV2._configV2.network.ssid, "YOUR_WIFI_SSID_HERE") == 0 || strcmp(WsV2._configV2.network.pass, "YOUR_WIFI_PASS_HERE") == 0) { - fsHalt("ERROR: Invalid network credentials in secrets.json! TO FIX: Please " - "change network_ssid and network_password to match your Adafruit IO " - "credentials!\n"); + HaltFilesystem( + "ERROR: Invalid network credentials in secrets.json! TO FIX: Please " + "change network_ssid and network_password to match your Adafruit IO " + "credentials!\n"); } // Close the file @@ -144,7 +147,8 @@ void WipperSnapper_LittleFS::parseSecrets() { Error message to print to serial console. */ /**************************************************************************/ -void WipperSnapper_LittleFS::fsHalt(String msg, ws_led_status_t status_state) { +void WipperSnapper_LittleFS::HaltFilesystem(String msg, + ws_led_status_t status_state) { statusLEDSolid(status_state); while (1) { WS_DEBUG_PRINTLN("Fatal Error: Halted execution!"); @@ -160,7 +164,7 @@ void WipperSnapper_LittleFS::fsHalt(String msg, ws_led_status_t status_state) { config.json file. */ /**************************************************************************/ -void WipperSnapper_LittleFS::GetSDCSPin() { +void WipperSnapper_LittleFS::GetPinSDCS() { // Attempt to open and deserialize the config.json file File file_cfg = LittleFS.open("/config.json"); if (!file_cfg) diff --git a/src/provisioning/littlefs/WipperSnapper_LittleFS.h b/src/provisioning/littlefs/WipperSnapper_LittleFS.h index 05b80875a..e150af3fe 100644 --- a/src/provisioning/littlefs/WipperSnapper_LittleFS.h +++ b/src/provisioning/littlefs/WipperSnapper_LittleFS.h @@ -30,10 +30,11 @@ class WipperSnapper_LittleFS { public: WipperSnapper_LittleFS(); ~WipperSnapper_LittleFS(); - void parseSecrets(); - void fsHalt(String msg, - ws_led_status_t status_state = WS_LED_STATUS_ERROR_RUNTIME); - void GetSDCSPin(); + void ParseFileSecrets(); + void + HaltFilesystem(String msg, + ws_led_status_t status_state = WS_LED_STATUS_ERROR_RUNTIME); + void GetPinSDCS(); }; extern Wippersnapper_V2 WsV2; #endif // WIPPERSNAPPER_LITTLEFS_H \ No newline at end of file diff --git a/src/provisioning/sdcard/ws_sdcard.cpp b/src/provisioning/sdcard/ws_sdcard.cpp index 14b945a05..45f04e278 100644 --- a/src/provisioning/sdcard/ws_sdcard.cpp +++ b/src/provisioning/sdcard/ws_sdcard.cpp @@ -16,36 +16,68 @@ /**************************************************************************/ /*! - @brief Constructs an instance of the Wippersnapper SD card class. + @brief Initializes the SD card. + @param pin_cs + The chip select pin for the SD card. + @returns True if the SD card was successfully initialized, False + otherwise. */ /**************************************************************************/ -ws_sdcard::ws_sdcard() +bool ws_sdcard::InitSdCard(uint8_t pin_cs) { #ifdef SD_USE_SPI_1 - : _sd_spi_cfg(WsV2.pin_sd_cs, DEDICATED_SPI, SPI_SD_CLOCK, &SPI1) { + SdSpiConfig _sd_spi_cfg(pin_cs, DEDICATED_SPI, SPI_SD_CLOCK, &SPI1); #else - : _sd_spi_cfg(WsV2.pin_sd_cs, DEDICATED_SPI, SPI_SD_CLOCK) { + SdSpiConfig _sd_spi_cfg(pin_cs, DEDICATED_SPI, SPI_SD_CLOCK); #endif - is_mode_offline = false; + if (!_sd.begin(_sd_spi_cfg)) { + WS_DEBUG_PRINTLN( + "[SD] Error: SD initialization failed.\nDo not reformat the " + "card!\nIs the card " + "correctly inserted?\nIs there a wiring/soldering problem\n"); + return false; + } + return true; +} + +/**************************************************************************/ +/*! + @brief Constructs an instance of the Wippersnapper SD card class. +*/ +/**************************************************************************/ +ws_sdcard::ws_sdcard() { _use_test_data = false; _is_soft_rtc = false; + _sz_cur_log_file = 0; _sd_cur_log_files = 0; - if (WsV2.pin_sd_cs == PIN_SD_CS_ERROR) - return; - - if (!_sd.begin(_sd_spi_cfg)) { + // Case 1: Try to initialize the SD card with the pin from the config file + bool did_init = false; + if (WsV2.pin_sd_cs != SD_CS_CFG_NOT_FOUND) { WS_DEBUG_PRINTLN( - "[SD] Runtime Error: SD initialization failed.\nDo not reformat the " - "card!\nIs the card " - "correctly inserted?\nIs there a wiring/soldering problem\n"); - is_mode_offline = false; - return; + "Attempting to initialize SD card with pin from config file"); + did_init = InitSdCard(WsV2.pin_sd_cs); + } + + // Case 2: Try to initialize the SD card with the default + // board SD CS pin (found within ws_boards.h) + if (!did_init) { + if (InitSdCard(SD_CS_PIN)) { +// Attempt to update the config file with the default pin +#ifndef OFFLINE_MODE_WOKWI + did_init = WsV2._fileSystemV2->AddSDCSPinToFileConfig(SD_CS_PIN); +#else // WOKWI Test Mode + WsV2.pin_sd_cs = 15; + did_init = true; +#endif + } } - // Card initialized - calculate file limits - is_mode_offline = true; - calculateFileLimits(); + // If sd initialized - configure the sd card + if (did_init) + ConfigureSDCard(); + + is_mode_offline = did_init; } /**************************************************************************/ @@ -60,11 +92,11 @@ ws_sdcard::~ws_sdcard() { is_mode_offline = false; } -void ws_sdcard::calculateFileLimits() { +void ws_sdcard::ConfigureSDCard() { // Calculate the maximum number of log files that can be stored on the SD card csd_t csd; if (!_sd.card()->readCSD(&csd)) { - WS_DEBUG_PRINTLN("[SD] Runtime Error: Could not read card information"); + WS_DEBUG_PRINTLN("[SD] Error: Could not read card information"); return; } @@ -91,13 +123,14 @@ bool ws_sdcard::InitDS1307() { _rtc_ds1307 = new RTC_DS1307(); if (!_rtc_ds1307->begin()) { if (!_rtc_ds1307->begin(&Wire1)) { - WS_DEBUG_PRINTLN("[SD] Runtime Error: Failed to initialize DS1307 RTC"); + WS_DEBUG_PRINTLN("[SD] Error: Failed to initialize DS1307 RTC"); delete _rtc_ds1307; return false; } } if (!_rtc_ds1307->isrunning()) _rtc_ds1307->adjust(DateTime(F(__DATE__), F(__TIME__))); + _cfg_i2c_addresses.push_back(0x68); // Disable auto-config for DS1307 return true; } @@ -113,13 +146,14 @@ bool ws_sdcard::InitDS3231() { _rtc_ds3231 = new RTC_DS3231(); if (!_rtc_ds3231->begin(&Wire)) { if (!_rtc_ds3231->begin(&Wire1)) { - WS_DEBUG_PRINTLN("[SD] Runtime Error: Failed to initialize DS3231 RTC"); + WS_DEBUG_PRINTLN("[SD] Error: Failed to initialize DS3231 RTC"); delete _rtc_ds3231; return false; } } if (_rtc_ds3231->lostPower()) _rtc_ds3231->adjust(DateTime(F(__DATE__), F(__TIME__))); + _cfg_i2c_addresses.push_back(0x68); // Disable auto-config for DS3231 return true; } @@ -133,11 +167,9 @@ bool ws_sdcard::InitDS3231() { bool ws_sdcard::InitPCF8523() { _rtc_pcf8523 = new RTC_PCF8523(); if (!_rtc_pcf8523->begin(&Wire)) { - WS_DEBUG_PRINTLN( - "[SD] Runtime Error: Failed to initialize PCF8523 RTC on WIRE"); + WS_DEBUG_PRINTLN("[SD] Error: Failed to initialize PCF8523 RTC on WIRE"); if (!_rtc_pcf8523->begin(&Wire1)) { - WS_DEBUG_PRINTLN( - "[SD] Runtime Error: Failed to initialize PCF8523 RTC on WIRE1"); + WS_DEBUG_PRINTLN("[SD] Error: Failed to initialize PCF8523 RTC on WIRE1"); delete _rtc_pcf8523; return false; } @@ -146,6 +178,7 @@ bool ws_sdcard::InitPCF8523() { _rtc_pcf8523->adjust(DateTime(F(__DATE__), F(__TIME__))); } _rtc_pcf8523->start(); + _cfg_i2c_addresses.push_back(0x68); // Disable auto-config for DS3231 return true; } @@ -195,10 +228,11 @@ bool ws_sdcard::ConfigureRTC(const char *rtc_type) { return InitPCF8523(); } else if (strcmp(rtc_type, "SOFT") == 0) { return InitSoftRTC(); - } else - WS_DEBUG_PRINTLN( - "[SD] Runtime Error: Unknown RTC type found in JSON string!"); - return false; + } + + WS_DEBUG_PRINTLN("[SD] Error: Unknown RTC type found in JSON string!"); + WS_DEBUG_PRINTLN("[SD] Falling back to soft RTC..."); + return InitSoftRTC(); } /**************************************************************************/ @@ -309,56 +343,31 @@ ws_sdcard::ParseSensorType(const char *sensor_type) { } } -bool ws_sdcard::ValidateJSONKey(const char *key, const char *error_msg) { - if (strcmp(key, UNKNOWN_VALUE) == 0) { - WS_DEBUG_PRINTLN(error_msg); - return false; - } - return true; -} - -/**************************************************************************/ -/*! - @brief Parses a DigitalIOAdd message from the JSON configuration file. - @param msg_DigitalIOAdd - The DigitalIOAdd message to populate. - @param pin - The GPIO pin name. - @param period - The desired period to read the sensor, in seconds. - @param value - The sensor value. - @param sample_mode - The sample mode. - @param direction - The GPIO pin direction. - @param pull - The GPIO pin pull. - @returns True if the DigitalIOAdd message was successfully parsed, - False otherwise. -*/ -/**************************************************************************/ bool ws_sdcard::ParseDigitalIOAdd( - wippersnapper_digitalio_DigitalIOAdd &msg_DigitalIOAdd, const char *pin, - float period, bool value, const char *sample_mode, const char *direction, - const char *pull) { - if (!ValidateJSONKey(pin, "[SD] Parsing Error: Digital pin name not found!")) + JsonObject &component, + wippersnapper_digitalio_DigitalIOAdd &msg_DigitalIOAdd) { + strcpy(msg_DigitalIOAdd.pin_name, component["pinName"] | UNKNOWN_VALUE); + msg_DigitalIOAdd.period = component["period"] | 0.0; + if (msg_DigitalIOAdd.period == 0.0) { + WS_DEBUG_PRINTLN("[SD] Parsing Error: Digital pin period less than 1.0 " + "seconds or not found!"); return false; - strcpy(msg_DigitalIOAdd.pin_name, pin); + } - if (period == 0.0) { - WS_DEBUG_PRINTLN("[SD] Parsing Error: Invalid pin period!"); - return false; + // Optionally set pin value + const char *value = component["value"]; + if (value != nullptr) { + msg_DigitalIOAdd.value = value; } - msg_DigitalIOAdd.period = period; - msg_DigitalIOAdd.value = value; - // Determine the sample mode - if (!ValidateJSONKey( - sample_mode, - "[SD] Parsing Error: Digital pin's sample mode not found!")) { + // Optionally determine pin sampling mode + const char *sample_mode = component["sampleMode"]; + if (sample_mode == nullptr) { + WS_DEBUG_PRINTLN( + "[SD] Parsing Error: Digital pin's sample mode not found!"); return false; - } else if (strcmp(sample_mode, "TIMER") == 0) { + } + if (strcmp(sample_mode, "TIMER") == 0) { msg_DigitalIOAdd.sample_mode = wippersnapper_digitalio_DigitalIOSampleMode_DIGITAL_IO_SAMPLE_MODE_TIMER; } else if (strcmp(sample_mode, "EVENT") == 0) { @@ -369,12 +378,15 @@ bool ws_sdcard::ParseDigitalIOAdd( String(sample_mode)); } - // Determine the pin direction and pull - if (!ValidateJSONKey( - direction, - "[SD] Parsing Error: Digital pin's direction not found!")) { + // Determine GPIO direction and pull mode + const char *direction = component["direction"]; + if (direction == nullptr) { + WS_DEBUG_PRINTLN("[SD] Parsing Error: Digital pin direction not found!"); return false; - } else if (strcmp(direction, "INPUT") == 0) { + } + const char *pull = component["pull"]; + + if (strcmp(direction, "INPUT") == 0) { if (pull != nullptr) { msg_DigitalIOAdd.gpio_direction = wippersnapper_digitalio_DigitalIODirection_DIGITAL_IO_DIRECTION_INPUT_PULL_UP; @@ -384,103 +396,35 @@ bool ws_sdcard::ParseDigitalIOAdd( } } else if (strcmp(direction, "OUTPUT") == 0) { WS_DEBUG_PRINTLN( - "[SD] Error - Can not set OUTPUT direction in offline mode!"); + "[SD] NotImplementedError - OUTPUT direction not supported!"); return false; } else { - WS_DEBUG_PRINTLN("[SD] Parsing Error: Unknown direction found: " + + WS_DEBUG_PRINTLN("[SD] Parsing Error: Unknown GPIO direction found: " + String(direction)); return false; } + return true; } -/**************************************************************************/ -/*! - @brief Parses an AnalogIOAdd message from the JSON configuration file. - @param msg_AnalogIOAdd - The AnalogIOAdd message to populate. - @param pin - The GPIO pin name. - @param period - The desired period to read the sensor, in seconds. - @param mode - The sensor read mode. - @returns True if the AnalogIOAdd message was successfully parsed, - False otherwise. -*/ -/**************************************************************************/ bool ws_sdcard::ParseAnalogIOAdd( - wippersnapper_analogio_AnalogIOAdd &msg_AnalogIOAdd, const char *pin, - float period, const char *mode) { - - if (!ValidateJSONKey(pin, "[SD] Parsing Error: Analog pin name not found!")) - return false; - strcpy(msg_AnalogIOAdd.pin_name, pin); - - if (period == 0.0) { + JsonObject &component, + wippersnapper_analogio_AnalogIOAdd &msg_AnalogIOAdd) { + strcpy(msg_AnalogIOAdd.pin_name, component["pinName"] | UNKNOWN_VALUE); + msg_AnalogIOAdd.period = component["period"] | 0.0; + if (msg_AnalogIOAdd.period < 1.0) { WS_DEBUG_PRINTLN("[SD] Parsing Error: Analog pin period less than 1.0 " "seconds or not found!"); return false; } - msg_AnalogIOAdd.period = period; - - if (!ValidateJSONKey(mode, - "[SD] Parsing Error: Analog pin read mode not found!")) - return false; - msg_AnalogIOAdd.read_mode = ParseSensorType(mode); + msg_AnalogIOAdd.read_mode = + ParseSensorType(component["mode"] | "UNSPECIFIED"); if (msg_AnalogIOAdd.read_mode == wippersnapper_sensor_SensorType_SENSOR_TYPE_UNSPECIFIED) { WS_DEBUG_PRINTLN("[SD] Parsing Error: Unknown read mode found: " + - String(mode)); - return false; - } - return true; -} - -bool ws_sdcard::ParseDS18X20Add( - wippersnapper_ds18x20_Ds18x20Add &msg_DS18X20Add, const char *pin, - int resolution, float period, int num_sensors, const char *sensor_type_1, - const char *sensor_type_2) { - - if (strcmp(pin, UNKNOWN_VALUE) == 0) { - WS_DEBUG_PRINTLN("[SD] Parsing Error: DS18X20 pin name not found!"); - return false; - } - strcpy(msg_DS18X20Add.onewire_pin, pin); - - if (resolution == 0) { - WS_DEBUG_PRINTLN( - "[SD] Parsing Error: DS18X20 sensor resolution not found!"); - return false; - } - msg_DS18X20Add.sensor_resolution = resolution; - - if (period == 0.0) { - WS_DEBUG_PRINTLN("[SD] Parsing Error: DS18X20 sensor period not found!"); + String(component["mode"])); return false; } - msg_DS18X20Add.period = period; - - if (num_sensors == 0) { - WS_DEBUG_PRINTLN("[SD] Parsing Error: DS18X20 sensor count not found!"); - return false; - } - msg_DS18X20Add.sensor_types_count = num_sensors; - - // Parse the first sensor type - if (strcmp(sensor_type_1, UNKNOWN_VALUE) == 0) { - WS_DEBUG_PRINTLN("[SD] Parsing Error: DS18X20 sensor type 1 not found!"); - return false; - } - msg_DS18X20Add.sensor_types[0] = ParseSensorType(sensor_type_1); - // Parse the second sensor type, if it exists - if (num_sensors == 2) { - if (strcmp(sensor_type_2, UNKNOWN_VALUE) == 0) { - WS_DEBUG_PRINTLN("[SD] Parsing Error: DS18X20 sensor type 2 not found!"); - return false; - } - msg_DS18X20Add.sensor_types[1] = ParseSensorType(sensor_type_2); - } return true; } @@ -496,6 +440,32 @@ uint32_t ws_sdcard::HexStrToInt(const char *hex_str) { return std::stoi(hex_str, nullptr, 16); } +/**************************************************************************/ +/*! + @brief Parses a DS18x20Add message from the JSON configuration file. + @param component + The JSON object to parse. + @param msg_ds18x20_add + The DS18x20Add message to populate. + @returns True if the DS18x20Add message was successfully parsed, False + otherwise. +*/ +/**************************************************************************/ +bool ws_sdcard::ParseDS18xAdd( + JsonObject &component, wippersnapper_ds18x20_Ds18x20Add &msg_ds18x20_add) { + strcpy(msg_ds18x20_add.onewire_pin, component["pinName"] | UNKNOWN_VALUE); + msg_ds18x20_add.sensor_resolution = component["sensorResolution"] | 0; + msg_ds18x20_add.period = component["period"] | 0.0; + msg_ds18x20_add.sensor_types_count = 0; + for (JsonObject components_0_ds18x20SensorType : + component["ds18x20SensorTypes"].as()) { + msg_ds18x20_add.sensor_types[msg_ds18x20_add.sensor_types_count] = + ParseSensorType(components_0_ds18x20SensorType["type"]); + msg_ds18x20_add.sensor_types_count++; + } + return true; +} + /**************************************************************************/ /*! @brief Parses an I2cDeviceAddOrReplace message from the JSON @@ -514,7 +484,7 @@ bool ws_sdcard::ParseI2cDeviceAddReplace( strcpy(msg_i2c_add.i2c_device_name, component["i2cDeviceName"] | UNKNOWN_VALUE); msg_i2c_add.i2c_device_period = component["period"] | 0.0; - if (msg_i2c_add.i2c_device_period == 0.0) { + if (msg_i2c_add.i2c_device_period < 0.0) { WS_DEBUG_PRINTLN("[SD] Parsing Error: Invalid I2C device period!"); return false; } @@ -529,6 +499,15 @@ bool ws_sdcard::ParseI2cDeviceAddReplace( msg_i2c_add.i2c_device_description.i2c_device_address = HexStrToInt(addr_device); + // MUXes, Seesaw, special devices should have an auto-init flag set to false + const char *is_auto = component["autoConfig"] | "true"; + if (strcmp(is_auto, "false") == 0) { + WS_DEBUG_PRINTLN("[SD] autoConfig = false, do not attempt to automatically " + "initialize this address"); + _cfg_i2c_addresses.push_back( + msg_i2c_add.i2c_device_description.i2c_device_address); + } + const char *addr_mux = component["i2cMuxAddress"] | "0x00"; msg_i2c_add.i2c_device_description.i2c_mux_address = HexStrToInt(addr_mux); @@ -547,6 +526,60 @@ bool ws_sdcard::ParseI2cDeviceAddReplace( return true; } +void ws_sdcard::ParseI2cAddScanned( + wippersnapper_i2c_I2cDeviceAddOrReplace &msg_i2c_add_scanned, + size_t scan_result_idx) { + uint32_t addr_device = + WsV2._i2c_controller->GetScanDeviceAddress(scan_result_idx); + msg_i2c_add_scanned.i2c_device_description.i2c_device_address = addr_device; + strcpy(msg_i2c_add_scanned.i2c_device_name, UNKNOWN_DRIVER_NAME); + msg_i2c_add_scanned.i2c_device_period = DEFAULT_SENSOR_PERIOD; + msg_i2c_add_scanned.has_i2c_device_description = true; + strcpy(msg_i2c_add_scanned.i2c_device_description.i2c_bus_scl, "default"); + strcpy(msg_i2c_add_scanned.i2c_device_description.i2c_bus_sda, "default"); + msg_i2c_add_scanned.i2c_device_description.i2c_mux_address = 0x00; + msg_i2c_add_scanned.i2c_device_description.i2c_mux_channel = 0xFFFF; +} + +bool ws_sdcard::AddI2cScanResultsToBuffer() { + for (size_t i = 0; i < WsV2._i2c_controller->GetScanDeviceCount(); i++) { + + // Was this address already provided by the config file? + bool skip_device = false; + for (size_t j = 0; j < _cfg_i2c_addresses.size(); j++) { + if (_cfg_i2c_addresses[j] == + WsV2._i2c_controller->GetScanDeviceAddress(i)) { + skip_device = true; + break; + } + } + + if (skip_device) { + WS_DEBUG_PRINTLN("[SD] Skipping I2C device - already in config file"); + continue; + } + + // Build the PB message + wippersnapper_signal_BrokerToDevice msg_signal = + wippersnapper_signal_BrokerToDevice_init_default; + wippersnapper_i2c_I2cDeviceAddOrReplace msg_i2c_add_replace = + wippersnapper_i2c_I2cDeviceAddOrReplace_init_default; + msg_signal.which_payload = + wippersnapper_signal_BrokerToDevice_i2c_device_add_replace_tag; + ParseI2cAddScanned(msg_i2c_add_replace, i); + msg_signal.payload.i2c_device_add_replace = msg_i2c_add_replace; + + if (!AddSignalMessageToSharedBuffer(msg_signal)) { + WS_DEBUG_PRINTLN("[SD] Error: Unable to add signal message(s) " + "to shared buffer!"); + return false; + } + WS_DEBUG_PRINT("[SD] Added I2C Device to shared buffer: 0x"); + WS_DEBUG_PRINTLN(WsV2._i2c_controller->GetScanDeviceAddress(i), HEX); + } + return true; +} + /**************************************************************************/ /*! @brief Pushes a signal message to the shared buffer. @@ -567,7 +600,7 @@ bool ws_sdcard::AddSignalMessageToSharedBuffer( if (!pb_get_encoded_size(&tempBufSz, wippersnapper_signal_BrokerToDevice_fields, &msg_signal)) { - WS_DEBUG_PRINTLN("[SD] Runtime Error: Unable to get signal message size!"); + WS_DEBUG_PRINTLN("[SD] Error: Unable to get signal message size!"); return false; } @@ -576,8 +609,7 @@ bool ws_sdcard::AddSignalMessageToSharedBuffer( pb_ostream_t ostream = pb_ostream_from_buffer(tempBuf.data(), tempBuf.size()); if (!ws_pb_encode(&ostream, wippersnapper_signal_BrokerToDevice_fields, &msg_signal)) { - WS_DEBUG_PRINTLN( - "[SD] Runtime Error: Unable to encode D2B signal message!"); + WS_DEBUG_PRINTLN("[SD] Error: Unable to encode D2B signal message!"); return false; } WsV2._sharedConfigBuffers.push_back(std::move(tempBuf)); @@ -594,7 +626,7 @@ bool ws_sdcard::AddSignalMessageToSharedBuffer( /**************************************************************************/ bool ws_sdcard::CreateNewLogFile() { if (_sd_cur_log_files >= _sd_max_num_log_files) { - WS_DEBUG_PRINTLN("[SD] Runtime Error: Maximum number of log files for SD " + WS_DEBUG_PRINTLN("[SD] Error: Maximum number of log files for SD " "card capacity reached!"); return false; } @@ -639,6 +671,39 @@ bool ws_sdcard::ValidateChecksum(JsonDocument &doc) { return true; } +/**************************************************************************/ +/*! + @brief Parses the exportedFromDevice object from the JSON configuration + file. + @param doc + The JSON document to parse. + @returns True if the exportedFromDevice object was successfully parsed, + False otherwise. +*/ +/**************************************************************************/ +bool ws_sdcard::ParseExportedFromDevice(JsonDocument &doc) { + JsonObject exportedFromDevice = doc["exportedFromDevice"]; + if (exportedFromDevice.isNull()) { + WS_DEBUG_PRINTLN( + "[SD] Error: exportedFromDevice not found in config file!"); + return false; + } + + // Mocks the device check-in + CheckIn(exportedFromDevice["totalGPIOPins"] | 0, + exportedFromDevice["totalAnalogPins"] | 0, + exportedFromDevice["referenceVoltage"] | 0.0); + setStatusLEDBrightness(exportedFromDevice["statusLEDBrightness"] | 0.3); + + // Configures RTC + const char *rtc_type = exportedFromDevice["rtc"] | "SOFT"; + if (!ConfigureRTC(rtc_type)) { + WS_DEBUG_PRINTLN("[SD] Error: Failed to to configure a RTC!"); + return false; + } + return true; +} + /**************************************************************************/ /*! @brief Searches for and parses the JSON configuration file and sets up @@ -647,17 +712,15 @@ bool ws_sdcard::ValidateChecksum(JsonDocument &doc) { was successfully configured. False otherwise. */ /**************************************************************************/ -bool ws_sdcard::parseConfigFile() { +bool ws_sdcard::ParseFileConfig() { DeserializationError error; - JsonDocument doc; - delay(5000); - // Parse configuration data #ifndef OFFLINE_MODE_DEBUG - WS_DEBUG_PRINTLN("[SD] Parsing config.json..."); - doc = WsV2._config_doc; + WS_DEBUG_PRINTLN("[SD] Deserializing config.json..."); + JsonDocument &doc = WsV2._fileSystemV2->GetDocCfg(); #else - // Use test data rather than data from the filesystem + JsonDocument doc; + // Use test data, not data from the filesystem if (!_use_test_data) { WS_DEBUG_PRINTLN("[SD] Parsing Serial Input..."); WS_DEBUG_PRINTLN(_serialInput); @@ -666,157 +729,130 @@ bool ws_sdcard::parseConfigFile() { WS_DEBUG_PRINTLN("[SD] Parsing Test Data..."); error = deserializeJson(doc, json_test_data, MAX_LEN_CFG_JSON); } -#endif - // It is not possible to continue running in offline mode without a valid - // config file if (error) { - WS_DEBUG_PRINT("[SD] Runtime Error: Unable to deserialize config.json"); + WS_DEBUG_PRINT("[SD] Error: Unable to deserialize config.json"); WS_DEBUG_PRINTLN("\nError Code: " + String(error.c_str())); return false; } +#endif + + if (doc.isNull()) { + WS_DEBUG_PRINTLN("[SD] Error: Document is null!"); + return false; + } + WS_DEBUG_PRINTLN("[SD] Successfully deserialized JSON config file!"); - // Check config.json file's integrity if (!ValidateChecksum(doc)) { WS_DEBUG_PRINTLN("[SD] Checksum mismatch, file has been modified from its " "original state!"); } - WS_DEBUG_PRINTLN("[SD] Checksum OK!"); - // Begin parsing the JSON document - JsonObject exportedFromDevice = doc["exportedFromDevice"]; - if (exportedFromDevice.isNull()) { - WS_DEBUG_PRINTLN("[SD] Runtime Error: Required exportedFromDevice not " - "found in config file!"); + if (!ParseExportedFromDevice(doc)) return false; - } - WS_DEBUG_PRINTLN("Parsing components array..."); - // TODO: It gets stuck here because we reformated how components works, - // try possibly adding another component like a button and then troubleshoot - JsonArray components_ar = doc["components"].as(); - if (components_ar.isNull()) { - WS_DEBUG_PRINTLN( - "[SD] Runtime Error: Required components array not found!"); + JsonArray components = doc["components"].as(); + if (!ParseComponents(components)) { + WS_DEBUG_PRINTLN("[SD] Error: Failed to parse components[]!"); return false; } - WS_DEBUG_PRINTLN("Parsing exportedFromDevice object..."); - - // We don't talk to IO here, mock an "offline" device check-in - CheckIn(exportedFromDevice["totalGPIOPins"] | 0, - exportedFromDevice["totalAnalogPins"] | 0, - exportedFromDevice["referenceVoltage"] | 0.0); - WS_DEBUG_PRINT("status LED brightness: "); - int exportedFromDevice_statusLEDBrightness = - exportedFromDevice["statusLEDBrightness"]; - WS_DEBUG_PRINTLN(exportedFromDevice_statusLEDBrightness); - setStatusLEDBrightness(exportedFromDevice["statusLEDBrightness"] | 0.3); - - WS_DEBUG_PRINTLN("Configuring RTC..."); -#ifndef OFFLINE_MODE_WOKWI - const char *json_rtc = exportedFromDevice["rtc"] | "SOFT"; - WS_DEBUG_PRINT("RTC Type: "); - WS_DEBUG_PRINTLN(json_rtc); - if (!ConfigureRTC(json_rtc)) { - WS_DEBUG_PRINTLN("[SD] Runtime Error: Failed to to configure RTC!"); + // Add the results of I2C scan to the shared buffer + if (!AddI2cScanResultsToBuffer()) { + WS_DEBUG_PRINTLN("[SD] Error: Unable to add I2C scan results to " + "shared buffer!"); return false; } -#endif - WS_DEBUG_PRINTLN("Parsing components array..."); + return true; +} - // Parse each component from JSON->PB and push into a shared buffer - for (JsonObject component : doc["components"].as()) { - wippersnapper_signal_BrokerToDevice msg_signal_b2d = - wippersnapper_signal_BrokerToDevice_init_default; +/**************************************************************************/ +/*! + @brief Parses the components array from the JSON configuration file. + @param doc + The JSON document to parse. + @returns True if the components array was successfully parsed, False + otherwise. +*/ +/**************************************************************************/ +bool ws_sdcard::ParseComponents(JsonArray &components) { + if (components.isNull()) { + WS_DEBUG_PRINTLN("[SD] Error: File missing required components[] array"); + return false; + } - // Parse the component API type + for (JsonObject component : components) { const char *component_api_type = component["componentAPI"]; - if (component_api_type == nullptr) { - WS_DEBUG_PRINTLN("[SD] Runtime Error: Missing component API type!"); - return false; + if (!component_api_type) { + WS_DEBUG_PRINT("[SD] Error: Missing componentAPI field, skipping.."); + continue; } - // Determine the component type and parse it into a PB message + bool success = false; + wippersnapper_signal_BrokerToDevice msg_signal_b2d = + wippersnapper_signal_BrokerToDevice_init_default; if (strcmp(component_api_type, "digitalio") == 0) { - WS_DEBUG_PRINTLN( - "[SD] DigitalIO component found, decoding JSON to PB..."); - wippersnapper_digitalio_DigitalIOAdd msg_DigitalIOAdd = + WS_DEBUG_PRINTLN("[SD] DigitalIO component found"); + wippersnapper_digitalio_DigitalIOAdd msg_add = wippersnapper_digitalio_DigitalIOAdd_init_default; - if (!ParseDigitalIOAdd( - msg_DigitalIOAdd, component["pinName"] | UNKNOWN_VALUE, - component["period"] | 0.0, component["value"], - component["sampleMode"] | UNKNOWN_VALUE, - component["direction"] | UNKNOWN_VALUE, component["pull"])) { - WS_DEBUG_PRINT( - "[SD] Runtime Error: Unable to parse DigitalIO Component, Pin: "); - WS_DEBUG_PRINTLN(component["pinName"] | UNKNOWN_VALUE); - return false; + success = ParseDigitalIOAdd(component, msg_add); + if (success) { + msg_signal_b2d.payload.digitalio_add = msg_add; + msg_signal_b2d.which_payload = + wippersnapper_signal_BrokerToDevice_digitalio_add_tag; } - - msg_signal_b2d.which_payload = - wippersnapper_signal_BrokerToDevice_digitalio_add_tag; - msg_signal_b2d.payload.digitalio_add = msg_DigitalIOAdd; } else if (strcmp(component_api_type, "analogio") == 0) { - WS_DEBUG_PRINTLN("[SD] AnalogIO component found, decoding JSON to PB..."); - wippersnapper_analogio_AnalogIOAdd msg_AnalogIOAdd = + WS_DEBUG_PRINTLN("[SD] AnalogIO component found"); + wippersnapper_analogio_AnalogIOAdd msg_add = wippersnapper_analogio_AnalogIOAdd_init_default; - if (!ParseAnalogIOAdd(msg_AnalogIOAdd, - component["pinName"] | UNKNOWN_VALUE, - component["period"] | 0.0, - component["analogReadMode"] | UNKNOWN_VALUE)) { - WS_DEBUG_PRINTLN( - "[SD] Runtime Error: Unable to parse AnalogIO Component, Pin: "); - WS_DEBUG_PRINTLN(component["pinName"] | UNKNOWN_VALUE); - return false; + success = ParseAnalogIOAdd(component, msg_add); + if (success) { + msg_signal_b2d.which_payload = + wippersnapper_signal_BrokerToDevice_analogio_add_tag; + msg_signal_b2d.payload.analogio_add = msg_add; } - - msg_signal_b2d.which_payload = - wippersnapper_signal_BrokerToDevice_analogio_add_tag; - msg_signal_b2d.payload.analogio_add = msg_AnalogIOAdd; } else if (strcmp(component_api_type, "ds18x20") == 0) { - WS_DEBUG_PRINTLN("[SD] Ds18x20 component found, decoding JSON to PB..."); - wippersnapper_ds18x20_Ds18x20Add msg_DS18X20Add = + WS_DEBUG_PRINTLN("[SD] Ds18x20 component found"); + wippersnapper_ds18x20_Ds18x20Add msg_add = wippersnapper_ds18x20_Ds18x20Add_init_default; - if (!ParseDS18X20Add(msg_DS18X20Add, component["pinName"] | UNKNOWN_VALUE, - component["sensorResolution"] | 0, - component["period"] | 0.0, - component["sensorTypeCount"] | 0, - component["sensorType1"] | UNKNOWN_VALUE, - component["sensorType2"] | UNKNOWN_VALUE)) { - WS_DEBUG_PRINTLN( - "[SD] Runtime Error: Unable to parse DS18X20 Component, Pin: "); - WS_DEBUG_PRINTLN(component["pinName"] | UNKNOWN_VALUE); - return false; + success = ParseDS18xAdd(component, msg_add); + if (success) { + msg_signal_b2d.which_payload = + wippersnapper_signal_BrokerToDevice_ds18x20_add_tag; + msg_signal_b2d.payload.ds18x20_add = msg_add; } - msg_signal_b2d.which_payload = - wippersnapper_signal_BrokerToDevice_ds18x20_add_tag; - msg_signal_b2d.payload.ds18x20_add = msg_DS18X20Add; } else if (strcmp(component_api_type, "i2c") == 0) { - WS_DEBUG_PRINTLN("[SD] I2C component found, decoding JSON to PB..."); - wippersnapper_i2c_I2cDeviceAddOrReplace msg_i2c_add_replace = + WS_DEBUG_PRINTLN("[SD] I2C component found in cfg"); + // Init for use=yes || use=auto + wippersnapper_i2c_I2cDeviceAddOrReplace msg_add = wippersnapper_i2c_I2cDeviceAddOrReplace_init_default; - if (!ParseI2cDeviceAddReplace(component, msg_i2c_add_replace)) { - WS_DEBUG_PRINTLN("[SD] Runtime Error: Unable to parse I2C Component"); - return false; + success = ParseI2cDeviceAddReplace(component, msg_add); + if (success) { + msg_signal_b2d.which_payload = + wippersnapper_signal_BrokerToDevice_i2c_device_add_replace_tag; + msg_signal_b2d.payload.i2c_device_add_replace = msg_add; + _cfg_i2c_addresses.push_back( + msg_add.i2c_device_description.i2c_device_address); } - msg_signal_b2d.which_payload = - wippersnapper_signal_BrokerToDevice_i2c_device_add_replace_tag; - msg_signal_b2d.payload.i2c_device_add_replace = msg_i2c_add_replace; } else { - WS_DEBUG_PRINTLN("[SD] Runtime Error: Unknown Component API Type: " + + WS_DEBUG_PRINTLN("[SD] Error: Unknown Component API: " + String(component_api_type)); - return false; + continue; + } + + if (!success) { + WS_DEBUG_PRINT("[SD] Error: Unable to parse component: "); + WS_DEBUG_PRINTLN(component["pinName"] | UNKNOWN_VALUE); + continue; } - // App handles the signal messages, in-order if (!AddSignalMessageToSharedBuffer(msg_signal_b2d)) { - WS_DEBUG_PRINTLN("[SD] Runtime Error: Unable to add signal message(s) " - "to shared buffer!"); + WS_DEBUG_PRINTLN("[SD] Error: Unable to add message to shared buffer"); return false; } } + return true; } @@ -1013,8 +1049,7 @@ bool ws_sdcard::LogJSONDoc(JsonDocument &doc) { File32 file; file = _sd.open(_log_filename, O_RDWR | O_CREAT | O_AT_END); if (!file) { - WS_DEBUG_PRINTLN( - "[SD] Runtime Error: Unable to open log file for writing!"); + WS_DEBUG_PRINTLN("[SD] Error: Unable to open log file for writing!"); return false; } BufferingPrint bufferedFile(file, 64); // Add buffering to the file diff --git a/src/provisioning/sdcard/ws_sdcard.h b/src/provisioning/sdcard/ws_sdcard.h index f269cc087..d9293711e 100644 --- a/src/provisioning/sdcard/ws_sdcard.h +++ b/src/provisioning/sdcard/ws_sdcard.h @@ -32,13 +32,17 @@ #define SPI_SD_CLOCK SD_SCK_MHZ(50) ///< Default SPI clock speed #endif -#define SD_FAT_TYPE 3 ///< SD type (3 = FAT16/FAT32 and exFAT) -#define PIN_SD_CS_ERROR 255 ///< Error code for invalid SD card CS pin +#define SD_FAT_TYPE 3 ///< SD type (3 = FAT16/FAT32 and exFAT) +#define SD_CS_CFG_NOT_FOUND \ + 255 ///< Error code if CS pin not found in config.json file #define UNKNOWN_VALUE "unknown" ///< Default unknown JSON field value #define MAX_SZ_LOG_FILE (512 * 1024 * 1024) ///< Maximum log file size, in Bytes #define MAX_LEN_CFG_JSON \ 4096 ///< Maximum length of the configuration JSON file, in Bytes +// auto-config +#define UNKNOWN_DRIVER_NAME "UNKNOWN_SCAN" ///< Default unknown driver name + // forward decl. class Wippersnapper_V2; @@ -52,8 +56,9 @@ class ws_sdcard { public: ws_sdcard(); ~ws_sdcard(); + bool InitSdCard(uint8_t pin_cs); bool isSDCardInitialized() { return is_mode_offline; } - bool parseConfigFile(); + bool ParseFileConfig(); bool CreateNewLogFile(); bool isModeOffline() { return is_mode_offline; } void waitForSerialConfig(); @@ -67,9 +72,9 @@ class ws_sdcard { bool LogI2cDeviceEvent(wippersnapper_i2c_I2cDeviceEvent *msg_device_event); private: - void calculateFileLimits(); + bool ParseExportedFromDevice(JsonDocument &doc); + void ConfigureSDCard(); bool ValidateChecksum(JsonDocument &doc); - bool ValidateJSONKey(const char *key, const char *error_msg); void CheckIn(uint8_t max_digital_pins, uint8_t max_analog_pins, float ref_voltage); bool ConfigureRTC(const char *rtc_type); @@ -81,19 +86,21 @@ class ws_sdcard { void TickSoftRTC(); uint32_t GetSoftRTCTime(); wippersnapper_sensor_SensorType ParseSensorType(const char *sensor_type); - bool ParseDigitalIOAdd(wippersnapper_digitalio_DigitalIOAdd &msg_DigitalIOAdd, - const char *pin, float period, bool value, - const char *sample_mode, const char *direction, - const char *pull); - bool ParseAnalogIOAdd(wippersnapper_analogio_AnalogIOAdd &msg_AnalogIOAdd, - const char *pin, float period, const char *mode); - bool ParseDS18X20Add(wippersnapper_ds18x20_Ds18x20Add &msg_DS18X20Add, - const char *pin, int resolution, float period, - int num_sensors, const char *sensor_type_1, - const char *sensor_type_2); + bool ParseComponents(JsonArray &components); + bool + ParseDigitalIOAdd(JsonObject &component, + wippersnapper_digitalio_DigitalIOAdd &msg_DigitalIOAdd); + bool ParseAnalogIOAdd(JsonObject &component, + wippersnapper_analogio_AnalogIOAdd &msg_AnalogIOAdd); + bool ParseDS18xAdd(JsonObject &component, + wippersnapper_ds18x20_Ds18x20Add &msg_ds18x20_add); bool ParseI2cDeviceAddReplace( JsonObject &component, wippersnapper_i2c_I2cDeviceAddOrReplace &msg_i2c_device_add_replace); + bool AddI2cScanResultsToBuffer(); + void ParseI2cAddScanned( + wippersnapper_i2c_I2cDeviceAddOrReplace &msg_i2c_add_scanned, + size_t scan_result_idx); uint32_t HexStrToInt(const char *hex_str); void BuildJSONDoc(JsonDocument &doc, uint8_t pin, float value, @@ -105,8 +112,6 @@ class ws_sdcard { bool LogJSONDoc(JsonDocument &doc); bool AddSignalMessageToSharedBuffer( wippersnapper_signal_BrokerToDevice &msg_signal); - - SdSpiConfig _sd_spi_cfg; ///< SPI configuration for the SD card SdFat _sd; ///< SD object from Adafruit SDFat library size_t _sd_capacity; ///< Capacity of the SD card, in Bytes size_t _sz_cur_log_file; ///< Size of the current log file, in Bytes @@ -125,6 +130,7 @@ class ws_sdcard { bool _is_soft_rtc; ///< True if a "soft rtc" is being used, False otherwise uint32_t _soft_rtc_counter; ///< Holds the counter for a "soft rtc" bool _use_test_data; ///< True if sample data is being used for testing + std::vector _cfg_i2c_addresses; }; extern Wippersnapper_V2 WsV2; #endif // WS_SDCARD_H \ No newline at end of file diff --git a/src/provisioning/tinyusb/Wippersnapper_FS.cpp b/src/provisioning/tinyusb/Wippersnapper_FS.cpp index 03bb68b90..c0398b02d 100644 --- a/src/provisioning/tinyusb/Wippersnapper_FS.cpp +++ b/src/provisioning/tinyusb/Wippersnapper_FS.cpp @@ -7,7 +7,7 @@ * please support Adafruit and open-source hardware by purchasing * products from Adafruit! * - * Copyright (c) Brent Rubell 2024 for Adafruit Industries. + * Copyright (c) Brent Rubell 2024-2025 for Adafruit Industries. * * BSD license, all text here must be included in any redistribution. * @@ -29,7 +29,7 @@ defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3_N4R2) || \ defined(ARDUINO_RASPBERRY_PI_PICO) || \ defined(ARDUINO_RASPBERRY_PI_PICO_2) || \ - defined(ARDUINO_ADAFRUIT_FEATHER_RP2040_ADALOGGER) || \ + defined(ARDUINO_ADAFRUIT_FEATHER_RP2040_ADALOGGER) || \ defined(ARDUINO_ADAFRUIT_METRO_RP2350) #include "Wippersnapper_FS.h" // On-board external flash (QSPI or SPI) macros should already @@ -58,6 +58,9 @@ Adafruit_FlashTransport_RP2040 flashTransport_v2; Adafruit_SPIFlash flash_v2(&flashTransport_v2); ///< SPIFlash object FatVolume wipperFatFs_v2; ///< File system object from Adafruit SDFat library Adafruit_USBD_MSC usb_msc_v2; /*!< USB mass storage object */ +Adafruit_USBD_CDC usb_cdc; /*!< USB CDC object */ +static bool _fs_changed = false; +static bool _did_init_msc = false; /**************************************************************************/ /*! @@ -102,50 +105,49 @@ FRESULT format_fs_fat12(void) { */ /**************************************************************************/ Wippersnapper_FS::Wippersnapper_FS() { - // Detach USB device during init. - TinyUSBDevice.detach(); - // Wait for detach - delay(500); + _fs_changed = false; + _did_init_msc = false; + + usb_cdc.begin(115200); + // Re-enumerate to allow cdc class begin() to take effect + if (TinyUSBDevice.mounted()) { + TinyUSBDevice.detach(); + delay(10); + TinyUSBDevice.attach(); + } // Attempt to initialize the flash chip if (!flash_v2.begin()) { setStatusLEDColor(RED); - fsHalt("Failed to initialize the flash chip!"); + HaltFilesystem("Failed to initialize the flash chip!"); } - // Attempt to initialize the filesystem - bool is_fs_formatted = wipperFatFs_v2.begin(&flash_v2); - // If we are not formatted, attempt to format the filesystem as fat12 - if (!is_fs_formatted) { + if (!wipperFatFs_v2.begin(&flash_v2)) { FRESULT rc = format_fs_fat12(); - if (rc != FR_OK) { setStatusLEDColor(RED); - fsHalt("FATAL ERROR: Failed to format the filesystem!"); + HaltFilesystem("FATAL ERROR: Failed to format the filesystem!"); } // Now that we have a formatted filesystem, we need to inititalize it if (!wipperFatFs_v2.begin(&flash_v2)) { setStatusLEDColor(RED); - fsHalt("FATAL ERROR: Failed to mount newly created filesystem!"); + HaltFilesystem("FATAL ERROR: Failed to mount newly created filesystem!"); } } // Write contents to the formatted filesystem - if (!writeFSContents()) { + if (!MakeDefaultFilesystem()) { setStatusLEDColor(RED); - fsHalt("FATAL ERROR: Could not write filesystem contents!"); + HaltFilesystem("FATAL ERROR: Could not write filesystem contents!"); } - // Initialize USB-MSC - initUSBMSC(); - // If we wrote a fresh secrets.json file, halt until user edits the file and // RESETs the device Signal to user that action must be taken (edit // secrets.json) if (_is_secrets_file_empty) { - writeToBootOut( + WriteFileBoot( "Please edit the secrets.json file. Then, reset your board.\n"); #ifdef USE_DISPLAY WsV2._ui_helper->show_scr_error( @@ -154,9 +156,10 @@ Wippersnapper_FS::Wippersnapper_FS() { "Please edit it to reflect your Adafruit IO and network credentials. " "When you're done, press RESET on the board."); #endif - fsHalt("The settings.json file on the WIPPER drive contains default " - "values\n. Using a text editor, edit it to reflect your Adafruit IO " - "and WiFi credentials. Then, reset the board."); + HaltFilesystem( + "The settings.json file on the WIPPER drive contains default " + "values\n. Using a text editor, edit it to reflect your Adafruit IO " + "and WiFi credentials. Then, reset the board."); } } @@ -176,7 +179,7 @@ Wippersnapper_FS::~Wippersnapper_FS() { config.json file. */ /**************************************************************************/ -void Wippersnapper_FS::GetSDCSPin() { +void Wippersnapper_FS::GetPinSDCS() { File32 file_cfg; DeserializationError error; // Attempt to open and deserialize the config.json file @@ -196,6 +199,7 @@ void Wippersnapper_FS::GetSDCSPin() { // Parse config.json and save the SD CS pin JsonObject exportedFromDevice = WsV2._config_doc["exportedFromDevice"]; WsV2.pin_sd_cs = exportedFromDevice["sd_cs_pin"] | 255; + file_cfg.flush(); file_cfg.close(); } @@ -222,6 +226,7 @@ bool disableMacOSIndexing() { return false; writeFile.close(); + refreshMassStorage(); return true; } @@ -233,28 +238,30 @@ bool disableMacOSIndexing() { @return True if filesystem initialized correctly, false otherwise. */ /**************************************************************************/ -bool Wippersnapper_FS::writeFSContents() { +bool Wippersnapper_FS::MakeDefaultFilesystem() { // If CircuitPython was previously installed - erase CircuitPython's default // filesystem - eraseCPFS(); + EraseCircuitPythonFS(); // If WipperSnapper was previously installed - remove the old // wippersnapper_boot_out.txt file - eraseBootFile(); + EraseFileBoot(); // Disble indexing on macOS disableMacOSIndexing(); // Create wippersnapper_boot_out.txt file - if (!createBootFile()) + if (!CreateFileBoot()) return false; // Check if secrets.json file already exists - if (!getSecretsFile()) { + if (!GetFileSecrets()) { // Create new secrets.json file and halt - createSecretsFile(); + CreateFileSecrets(); _is_secrets_file_empty = true; } + + CreateFileConfig(); return true; } @@ -263,11 +270,11 @@ bool Wippersnapper_FS::writeFSContents() { @brief Initializes the USB MSC device. */ /**************************************************************************/ -void Wippersnapper_FS::initUSBMSC() { +void Wippersnapper_FS::InitUsbMsc() { // Set disk vendor id, product id and revision with string up to 8, 16, 4 // characters respectively usb_msc_v2.setID("Adafruit", "External Flash", "1.0"); - // Set callback + // Set r/w callbacks usb_msc_v2.setReadWriteCallback(qspi_msc_read_cb_v2, qspi_msc_write_cb_v2, qspi_msc_flush_cb_v2); @@ -277,25 +284,20 @@ void Wippersnapper_FS::initUSBMSC() { // MSC is ready for read/write usb_msc_v2.setUnitReady(true); + // Setup callback for when MSC ready + _fs_changed = false; + usb_msc_v2.setReadyCallback(0, msc_ready_callback); + // init MSC usb_msc_v2.begin(); - // If already enumerated, additional class driverr begin() e.g msc, hid, midi - // won't take effect until re-enumeration - // Attach MSC and wait for enumeration - TinyUSBDevice.attach(); - delay(500); -} - -/**************************************************************************/ -/*! - @brief Checks if secrets.json file exists on the flash filesystem. - @returns True if secrets.json file exists, False otherwise. -*/ -/**************************************************************************/ -bool Wippersnapper_FS::getSecretsFile() { - // Does secrets.json file exist? - return wipperFatFs_v2.exists("/secrets.json"); + // Re-enumerate to allow msc class begin() to take effect + if (TinyUSBDevice.mounted()) { + TinyUSBDevice.detach(); + delay(10); + TinyUSBDevice.attach(); + } + _did_init_msc = true; } /**************************************************************************/ @@ -303,7 +305,7 @@ bool Wippersnapper_FS::getSecretsFile() { @brief Erases the default CircuitPython filesystem if it exists. */ /**************************************************************************/ -void Wippersnapper_FS::eraseCPFS() { +void Wippersnapper_FS::EraseCircuitPythonFS() { if (wipperFatFs_v2.exists("/boot_out.txt")) { wipperFatFs_v2.remove("/boot_out.txt"); wipperFatFs_v2.remove("/code.py"); @@ -317,7 +319,7 @@ void Wippersnapper_FS::eraseCPFS() { @brief Erases the existing "wipper_boot_out.txt" file from the FS. */ /**************************************************************************/ -void Wippersnapper_FS::eraseBootFile() { +void Wippersnapper_FS::EraseFileBoot() { // overwrite previous boot_out file on each boot if (wipperFatFs_v2.exists("/wipper_boot_out.txt")) wipperFatFs_v2.remove("/wipper_boot_out.txt"); @@ -328,7 +330,7 @@ void Wippersnapper_FS::eraseBootFile() { @brief Creates or overwrites `wipper_boot_out.txt` file to FS. */ /**************************************************************************/ -bool Wippersnapper_FS::createBootFile() { +bool Wippersnapper_FS::CreateFileBoot() { bool is_success = false; char sMAC[18] = {0}; @@ -360,6 +362,7 @@ bool Wippersnapper_FS::createBootFile() { bootFile.flush(); bootFile.close(); + refreshMassStorage(); is_success = true; } else { bootFile.close(); @@ -367,12 +370,144 @@ bool Wippersnapper_FS::createBootFile() { return is_success; } +/**************************************************************************/ +/*! + @brief Creates a default config document in memory. +*/ +/**************************************************************************/ +void Wippersnapper_FS::CreateFileConfig() { + // Load config.json into memory, if it already exists on the FS + if (wipperFatFs_v2.exists("/config.json")) { + File32 file_cfg = wipperFatFs_v2.open("/config.json", FILE_READ); + if (file_cfg) { + DeserializationError error = deserializeJson(_doc_cfg, file_cfg); + // if (error) + // HaltFilesystem("Error unable to parse config.json on WIPPER drive!"); + // Remove config from the filesystem + file_cfg.close(); + wipperFatFs_v2.remove("/config.json"); + flash_v2.syncBlocks(); + + // Check if the config.json file has the required keys + if (!_doc_cfg.containsKey("exportedFromDevice")) { + // Build exportedFromDevice object + JsonObject exportedFromDevice = + _doc_cfg["exportedFromDevice"].to(); + exportedFromDevice["sd_cs_pin"] = 255; + exportedFromDevice["referenceVoltage"] = 0; + exportedFromDevice["totalGPIOPins"] = 0; + exportedFromDevice["totalAnalogPins"] = 0; + exportedFromDevice["statusLEDBrightness"] = 0.3; + } + + if (!_doc_cfg.containsKey("components")) { + // Build components array + _doc_cfg["components"].to(); + } + return; + } + } + + // Create a default configConfig structure in a new doc + _doc_cfg.clear(); + JsonObject exportedFromDevice = + _doc_cfg["exportedFromDevice"].to(); + exportedFromDevice["sd_cs_pin"] = 255; + exportedFromDevice["referenceVoltage"] = 0; + exportedFromDevice["totalGPIOPins"] = 0; + exportedFromDevice["totalAnalogPins"] = 0; + exportedFromDevice["statusLEDBrightness"] = 0.3; + JsonArray components = _doc_cfg["components"].to(); +} + +/**************************************************************************/ +/*! + @brief Adds the SD CS pin to the `config.json` file. + @param pin + The Chip Select pin to add to the `config.json` file. + @returns True if the pin was successfully added, False otherwise. +*/ +/**************************************************************************/ +bool Wippersnapper_FS::AddSDCSPinToFileConfig(uint8_t pin) { + // Modify the in-memory JSON doc + _doc_cfg["exportedFromDevice"]["sd_cs_pin"] = pin; + return true; +} + +/********************************************************************************/ +/*! + @brief Adds an I2C device to the `config.json` file. + @param address + The I2C device's address. + @param period + The period at which the device should be polled. + @param driver_name + The name of the driver. +*/ +/********************************************************************************/ +void Wippersnapper_FS::AddI2cDeviceToFileConfig( + uint32_t address, const char *driver_name, const char **sensor_type_strings, + size_t sensor_types_count) { + // Write to components[] on the in-memory config document + JsonObject new_component = _doc_cfg["components"].add(); + new_component["name"] = driver_name; + new_component["componentAPI"] = "i2c"; + new_component["i2cDeviceName"] = driver_name; + new_component["period"] = 30; + new_component["autoConfig"] = "true"; + char address_str[6]; + sprintf(address_str, "0x%02X", address); + new_component["i2cDeviceAddress"] = address_str; + JsonArray new_component_sensor_types = + new_component["i2cDeviceSensorTypes"].to(); + for (size_t i = 0; i < sensor_types_count; i++) { + new_component_sensor_types[i]["type"] = sensor_type_strings[i]; + } +} + +/**************************************************************************/ +/*! + @brief Writes the in-memory config document to the filesystem. + @returns True if the file was successfully written, False otherwise. +*/ +/**************************************************************************/ +bool Wippersnapper_FS::WriteFileConfig() { + // Write the document to the filesystem + File32 file_cfg = wipperFatFs_v2.open("/config.json", FILE_WRITE); + if (!file_cfg) { + HaltFilesystem("Could not create the config file!"); + return false; + } + _doc_cfg.shrinkToFit(); + size_t bytes_written = serializeJsonPretty(_doc_cfg, file_cfg); + + // Attempt to clear the cache and sync the FS + file_cfg.close(); + file_cfg.flush(); + flash_v2.syncBlocks(); + refreshMassStorage(); + delay(500); + InitUsbMsc(); + return true; +} + +/**************************************************************************/ +/*! + @brief Checks if secrets.json file exists on the flash filesystem. + @returns True if secrets.json file exists, False otherwise. +*/ +/**************************************************************************/ +bool Wippersnapper_FS::GetFileSecrets() { + // Does secrets.json file exist? + return wipperFatFs_v2.exists("/secrets.json"); +} + /**************************************************************************/ /*! @brief Creates a default secrets.json file on the filesystem. */ /**************************************************************************/ -void Wippersnapper_FS::createSecretsFile() { +void Wippersnapper_FS::CreateFileSecrets() { // Open file for writing File32 secretsFile = wipperFatFs_v2.open("/secrets.json", FILE_WRITE); @@ -394,6 +529,7 @@ void Wippersnapper_FS::createSecretsFile() { // Flush and close file secretsFile.flush(); secretsFile.close(); + refreshMassStorage(); delay(2500); } @@ -402,20 +538,20 @@ void Wippersnapper_FS::createSecretsFile() { @brief Parses a secrets.json file on the flash filesystem. */ /**************************************************************************/ -void Wippersnapper_FS::parseSecrets() { +void Wippersnapper_FS::ParseFileSecrets() { // Attempt to open the secrets.json file for reading File32 secretsFile = wipperFatFs_v2.open("/secrets.json"); if (!secretsFile) { - fsHalt("ERROR: Could not open secrets.json file for reading!"); + HaltFilesystem("ERROR: Could not open secrets.json file for reading!"); } // Attempt to deserialize the file's JSON document JsonDocument doc; DeserializationError error = deserializeJson(doc, secretsFile); if (error) { - fsHalt(String("ERROR: Unable to parse secrets.json file - " - "deserializeJson() failed with code") + - error.c_str()); + HaltFilesystem(String("ERROR: Unable to parse secrets.json file - " + "deserializeJson() failed with code") + + error.c_str()); } if (doc.containsKey("network_type_wifi")) { @@ -436,8 +572,9 @@ void Wippersnapper_FS::parseSecrets() { WS_DEBUG_PRINT("Network count: "); WS_DEBUG_PRINTLN(altNetworkCount); if (altNetworkCount == 0) { - fsHalt("ERROR: No alternative network entries found under " - "network_type_wifi.alternative_networks in secrets.json!"); + HaltFilesystem( + "ERROR: No alternative network entries found under " + "network_type_wifi.alternative_networks in secrets.json!"); } // check if over 3, warn user and take first three for (int i = 0; i < altNetworkCount; i++) { @@ -455,11 +592,11 @@ void Wippersnapper_FS::parseSecrets() { } WsV2._isWiFiMultiV2 = true; } else { - fsHalt("ERROR: Unrecognised value type for " - "network_type_wifi.alternative_networks in secrets.json!"); + HaltFilesystem("ERROR: Unrecognised value type for " + "network_type_wifi.alternative_networks in secrets.json!"); } } else { - fsHalt("ERROR: Could not find network_type_wifi in secrets.json!"); + HaltFilesystem("ERROR: Could not find network_type_wifi in secrets.json!"); } // Extract a config struct from the JSON document @@ -468,7 +605,7 @@ void Wippersnapper_FS::parseSecrets() { // Validate the config struct is not filled with default values if (strcmp(WsV2._configV2.aio_user, "YOUR_IO_USERNAME_HERE") == 0 || strcmp(WsV2._configV2.aio_key, "YOUR_IO_KEY_HERE") == 0) { - writeToBootOut( + WriteFileBoot( "ERROR: Invalid IO credentials in secrets.json! TO FIX: Please change " "io_username and io_key to match your Adafruit IO credentials!\n"); #ifdef USE_DISPLAY @@ -478,16 +615,16 @@ void Wippersnapper_FS::parseSecrets() { "please " "change it to match your Adafruit IO credentials. Then, press RESET."); #endif - fsHalt( + HaltFilesystem( "ERROR: Invalid IO credentials in secrets.json! TO FIX: Please change " "io_username and io_key to match your Adafruit IO credentials!"); } if (strcmp(WsV2._configV2.network.ssid, "YOUR_WIFI_SSID_HERE") == 0 || strcmp(WsV2._configV2.network.pass, "YOUR_WIFI_PASS_HERE") == 0) { - writeToBootOut("ERROR: Invalid network credentials in secrets.json! TO " - "FIX: Please change network_ssid and network_password to " - "match your Adafruit IO credentials!\n"); + WriteFileBoot("ERROR: Invalid network credentials in secrets.json! TO " + "FIX: Please change network_ssid and network_password to " + "match your Adafruit IO credentials!\n"); #ifdef USE_DISPLAY WsV2._ui_helper->show_scr_error( "INVALID NETWORK", @@ -495,21 +632,23 @@ void Wippersnapper_FS::parseSecrets() { "are invalid, please change it to match your WiFi credentials. Then, " "press RESET."); #endif - fsHalt("ERROR: Invalid network credentials in secrets.json! TO FIX: Please " - "change network_ssid and network_password to match your Adafruit IO " - "credentials!"); + HaltFilesystem( + "ERROR: Invalid network credentials in secrets.json! TO FIX: Please " + "change network_ssid and network_password to match your Adafruit IO " + "credentials!"); } - writeToBootOut("Secrets Contents\n"); - writeToBootOut("Network Info\n: "); - writeToBootOut(WsV2._configV2.network.ssid); - writeToBootOut(WsV2._configV2.network.pass); - writeToBootOut("IO Creds.\n: "); - writeToBootOut(WsV2._configV2.aio_user); - writeToBootOut(WsV2._configV2.aio_key); + WriteFileBoot("Secrets Contents\n"); + WriteFileBoot("Network Info\n: "); + WriteFileBoot(WsV2._configV2.network.ssid); + WriteFileBoot(WsV2._configV2.network.pass); + WriteFileBoot("IO Creds.\n: "); + WriteFileBoot(WsV2._configV2.aio_user); + WriteFileBoot(WsV2._configV2.aio_key); // Close secrets.json file secretsFile.close(); + refreshMassStorage(); } /**************************************************************************/ @@ -519,14 +658,15 @@ void Wippersnapper_FS::parseSecrets() { PROGMEM string. */ /**************************************************************************/ -void Wippersnapper_FS::writeToBootOut(PGM_P str) { +void Wippersnapper_FS::WriteFileBoot(PGM_P str) { // Append error output to FS File32 bootFile = wipperFatFs_v2.open("/wipper_boot_out.txt", FILE_WRITE); if (!bootFile) - fsHalt("ERROR: Unable to open wipper_boot_out.txt for logging!"); + HaltFilesystem("ERROR: Unable to open wipper_boot_out.txt for logging!"); bootFile.print(str); bootFile.flush(); bootFile.close(); + refreshMassStorage(); } /**************************************************************************/ @@ -536,7 +676,11 @@ void Wippersnapper_FS::writeToBootOut(PGM_P str) { Error message to print to serial console. */ /**************************************************************************/ -void Wippersnapper_FS::fsHalt(String msg) { +void Wippersnapper_FS::HaltFilesystem(String msg) { + if (!_did_init_msc) { + WS_DEBUG_PRINTLN("HaltFilesystem: InitUsbMsc"); + InitUsbMsc(); + } TinyUSBDevice.attach(); delay(500); statusLEDSolid(WS_LED_STATUS_FS_WRITE); @@ -555,7 +699,12 @@ void Wippersnapper_FS::fsHalt(String msg) { Error message to print to serial console. */ /**************************************************************************/ -void Wippersnapper_FS::fsHalt(String msg, ws_led_status_t ledStatusColor) { +void Wippersnapper_FS::HaltFilesystem(String msg, + ws_led_status_t ledStatusColor) { + if (!_did_init_msc) { + WS_DEBUG_PRINTLN("HaltFilesystem: InitUsbMsc"); + InitUsbMsc(); + } TinyUSBDevice.attach(); delay(500); statusLEDSolid(ledStatusColor); @@ -573,7 +722,7 @@ void Wippersnapper_FS::fsHalt(String msg, ws_led_status_t ledStatusColor) { @brief Creates a default display_config.json file on the filesystem. */ /**************************************************************************/ -void Wippersnapper_FS::createDisplayConfig() { +void Wippersnapper_FS::CreateDisplayCfg() { // Open file for writing File32 displayFile = wipperFatFs_v2.open("/display_config.json", FILE_WRITE); @@ -592,14 +741,15 @@ void Wippersnapper_FS::createDisplayConfig() { // Create and fill JSON document from displayConfig JsonDocument doc; if (!doc.set(displayConfig)) { - fsHalt("ERROR: Unable to set displayConfig, no space in arduinoJSON " - "document!"); + HaltFilesystem( + "ERROR: Unable to set displayConfig, no space in arduinoJSON " + "document!"); } // Write the file out to the filesystem serializeJsonPretty(doc, displayFile); displayFile.flush(); displayFile.close(); - delay(2500); // give FS some time to write the file + refreshMassStorage(); } /**************************************************************************/ @@ -609,32 +759,34 @@ void Wippersnapper_FS::createDisplayConfig() { displayConfig struct to populate. */ /**************************************************************************/ -void Wippersnapper_FS::parseDisplayConfig(displayConfig &dispCfg) { +void Wippersnapper_FS::ParseFileDisplayCfg(displayConfig &dispCfg) { // Check if display_config.json file exists, if not, generate it if (!wipperFatFs_v2.exists("/display_config.json")) { WS_DEBUG_PRINTLN("Could not find display_config.json, generating..."); #ifdef ARDUINO_FUNHOUSE_ESP32S2 - createDisplayConfig(); // generate a default display_config.json for - // FunHouse + CreateDisplayCfg(); // generate a default display_config.json for + // FunHouse #endif } // Attempt to open file for JSON parsing File32 file = wipperFatFs_v2.open("/display_config.json", FILE_READ); if (!file) { - fsHalt("FATAL ERROR: Unable to open display_config.json for parsing"); + HaltFilesystem( + "FATAL ERROR: Unable to open display_config.json for parsing"); } // Attempt to deserialize the file's json document JsonDocument doc; DeserializationError error = deserializeJson(doc, file); if (error) { - fsHalt(String("FATAL ERROR: Unable to parse display_config.json - " - "deserializeJson() failed with code") + - error.c_str()); + HaltFilesystem(String("FATAL ERROR: Unable to parse display_config.json - " + "deserializeJson() failed with code") + + error.c_str()); } // Close the file, we're done with it file.close(); + refreshMassStorage(); // Extract a displayConfig struct from the JSON document dispCfg = doc.as(); } @@ -681,6 +833,22 @@ int32_t qspi_msc_write_cb_v2(uint32_t lba, uint8_t *buffer, uint32_t bufsize) { return flash_v2.writeBlocks(lba, buffer, bufsize / 512) ? bufsize : -1; } +/**************************************************************************/ +/*! + @brief Callback invoked when the host sends a Test Unit Ready command. + @returns True if the host can read/write the LUN. +*/ +/**************************************************************************/ +bool msc_ready_callback(void) { + // if fs has changed, mark unit as not ready temporarily + // to force PC to flush cache + bool ret = !_fs_changed; + _fs_changed = false; + return ret; +} + +void refreshMassStorage(void) { _fs_changed = true; } + /***************************************************************************/ /*! @brief Callback invoked when WRITE10 command is completed (status @@ -692,6 +860,7 @@ void qspi_msc_flush_cb_v2(void) { flash_v2.syncBlocks(); // clear file system's cache to force refresh wipperFatFs_v2.cacheClear(); + _fs_changed = true; } //--------------------------------------------------------------------+ diff --git a/src/provisioning/tinyusb/Wippersnapper_FS.h b/src/provisioning/tinyusb/Wippersnapper_FS.h index e2717ead0..f548e85f9 100644 --- a/src/provisioning/tinyusb/Wippersnapper_FS.h +++ b/src/provisioning/tinyusb/Wippersnapper_FS.h @@ -7,7 +7,7 @@ * please support Adafruit and open-source hardware by purchasing * products from Adafruit! * - * Copyright (c) Brent Rubell 2021-2024 for Adafruit Industries. + * Copyright (c) Brent Rubell 2021-2025 for Adafruit Industries. * * BSD license, all text here must be included in any redistribution. * @@ -32,7 +32,8 @@ struct displayConfig; int32_t qspi_msc_write_cb_v2(uint32_t lba, uint8_t *buffer, uint32_t bufsize); int32_t qspi_msc_read_cb_v2(uint32_t lba, void *buffer, uint32_t bufsize); void qspi_msc_flush_cb_v2(void); - +bool msc_ready_callback(void); +void refreshMassStorage(void); /***************************************************************************/ /*! @brief Class that handles Wippersnapper's optional filesystem commands @@ -43,30 +44,35 @@ class Wippersnapper_FS { public: Wippersnapper_FS(); ~Wippersnapper_FS(); - - void initUSBMSC(); - - void GetSDCSPin(); - - bool writeFSContents(); - void fsHalt(String msg); - void fsHalt(String msg, ws_led_status_t ledStatusColor); - void eraseCPFS(); - - bool createBootFile(); - void writeToBootOut(PGM_P str); - void eraseBootFile(); - - // Secrets.json API - void createSecretsFile(); - bool getSecretsFile(); - void parseSecrets(); + void InitUsbMsc(); + // Filesystem + bool MakeDefaultFilesystem(); + void HaltFilesystem(String msg); + void HaltFilesystem(String msg, ws_led_status_t ledStatusColor); + void EraseCircuitPythonFS(); + // boot.txt + bool CreateFileBoot(); + void WriteFileBoot(PGM_P str); + void EraseFileBoot(); + // secrets.json + void CreateFileSecrets(); + bool GetFileSecrets(); + void ParseFileSecrets(); #ifdef ARDUINO_FUNHOUSE_ESP32S2 - void parseDisplayConfig(displayConfig &displayFile); - void createDisplayConfig(); + void ParseFileDisplayCfg(displayConfig &displayFile); + void CreateDisplayCfg(); #endif + // config.json + void CreateFileConfig(); + void GetPinSDCS(); + bool AddSDCSPinToFileConfig(uint8_t pin); + void AddI2cDeviceToFileConfig(uint32_t address, const char *driver_name, const char **sensor_type_strings = nullptr, size_t sensor_types_count = 0); + bool WriteFileConfig(); + // getter for _doc_cfg + JsonDocument &GetDocCfg() { return _doc_cfg; } private: bool _is_secrets_file_empty = false; + JsonDocument _doc_cfg; }; extern Wippersnapper_V2 WsV2; -#endif // Wippersnapper_FS_V2_V2_H \ No newline at end of file +#endif // Wippersnapper_FS_H \ No newline at end of file diff --git a/src/ws_adapters.h b/src/ws_adapters.h index 72bba5072..3459d437e 100644 --- a/src/ws_adapters.h +++ b/src/ws_adapters.h @@ -22,22 +22,31 @@ #if defined(ADAFRUIT_METRO_M4_EXPRESS) || \ defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE) || defined(ADAFRUIT_PYPORTAL) || \ defined(ADAFRUIT_PYPORTAL_M4_TITANO) || defined(USE_AIRLIFT) +#define SD_CS_PIN 10 #include "adapters/wifi/ws_wifi_airlift.h" typedef ws_wifi_airlift ws_adapter_wifi; // ESP8266 networking adapter #elif defined(ARDUINO_ARCH_ESP8266) +#define SD_CS_PIN 15 #include "adapters/wifi/ws_wifi_esp8266.h" typedef ws_wifi_esp8266 ws_adapter_wifi; +#elif defined(ARDUINO_ESP32_DEV) || defined(ESP32_DEV) +#define SD_CS_PIN 15 +#include "adapters/wifi/ws_wifi_esp32.h" +typedef ws_wifi_esp32 ws_adapter_wifi; // ESP32 networking adapter #elif defined(ARDUINO_ARCH_ESP32) +#define SD_CS_PIN 33 #include "adapters/wifi/ws_wifi_esp32.h" typedef ws_wifi_esp32 ws_adapter_wifi; // Networking adapters for Raspberry Pi Pico W-series #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) +#define SD_CS_PIN 17 #include "adapters/wifi/ws_wifi_pico.h" typedef ws_wifi_pico ws_adapter_wifi; // Networking adapter for Arduino Nano 33 IoT and MKR WiFi 1010 #elif defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRWIFI1010) +#define SD_CS_PIN 33 #include "adapters/wifi/ws_wifi_ninafw.h" typedef ws_wifi_ninafw ws_adapter_wifi; /** @@ -47,6 +56,7 @@ typedef ws_wifi_ninafw ws_adapter_wifi; defined(ARDUINO_RASPBERRY_PI_PICO) || \ defined(ARDUINO_ADAFRUIT_FEATHER_RP2040_ADALOGGER) || \ defined(ARDUINO_ADAFRUIT_METRO_RP2350) +#define SD_CS_PIN 23 #include "adapters/offline/ws_offline_pico.h" typedef ws_offline_pico ws_adapter_offline; #else diff --git a/src/ws_boards.h b/src/ws_boards.h new file mode 100644 index 000000000..874572541 --- /dev/null +++ b/src/ws_boards.h @@ -0,0 +1,244 @@ +/*! + * @file ws_boards.h + * + * This file determines hardware/board type at compile-time. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2020-2025 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ + +#ifndef ADAFRUIT_WIPPERSNAPPER_BOARDS_H +#define ADAFRUIT_WIPPERSNAPPER_BOARDS_H + +#if defined(ADAFRUIT_PYPORTAL) +#define BOARD_ID "pyportal-tinyusb" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN 2 +#define STATUS_NEOPIXEL_NUM 1 +#define SD_CS_PIN 10 +#elif defined(ADAFRUIT_PYPORTAL_M4_TITANO) +#define BOARD_ID "pyportal-titano-tinyusb" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN 2 +#define STATUS_NEOPIXEL_NUM 1 +#define SD_CS_PIN 10 +#elif defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE) +#define BOARD_ID "metro-m4-airliftlite-tinyusb" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN 40 +#define STATUS_NEOPIXEL_NUM 1 +#define SD_CS_PIN 10 +#elif defined(ARDUINO_FUNHOUSE_ESP32S2) +#define BOARD_ID "funhouse" ///< Board ID +#define USE_TINYUSB ///< Enable TinyUSB +#define USE_STATUS_DOTSTAR ///< Enable DotStar +#define USE_DISPLAY ///< Enable Display +#define STATUS_DOTSTAR_PIN_DATA PIN_DOTSTAR_DATA ///< DotStar Data Pin +#define STATUS_DOTSTAR_PIN_CLK PIN_DOTSTAR_CLOCK ///< DotStar Clock Pin +#define STATUS_DOTSTAR_NUM 5 ///< Number of DotStar LEDs +#define STATUS_DOTSTAR_COLOR_ORDER DOTSTAR_GBR ///< DotStar Color Order +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 +#elif defined(ARDUINO_METRO_ESP32S2) +#define BOARD_ID "metroesp32s2" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN 45 +#define STATUS_NEOPIXEL_NUM 1 +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 +#elif defined(ARDUINO_METRO_ESP32S3) +#define BOARD_ID "metroesp32s3" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN 46 +#define STATUS_NEOPIXEL_NUM 1 +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 +#elif defined(ARDUINO_MAGTAG29_ESP32S2) +#define BOARD_ID "magtag" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN 1 +#define STATUS_NEOPIXEL_NUM 4 +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2) +#define BOARD_ID "feather-esp32s2" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN 33 +#define STATUS_NEOPIXEL_NUM 1 +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 10 +#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2_TFT) +#define BOARD_ID "feather-esp32s2-tft" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN 33 +#define STATUS_NEOPIXEL_NUM 1 +#define PIN_I2C_POWER_INVERTED 7 +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2_REVTFT) +#define BOARD_ID "feather-esp32s2-reverse-tft" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define STATUS_NEOPIXEL_NUM NEOPIXEL_NUM +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3_NOPSRAM) +#define BOARD_ID "feather-esp32s3" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define STATUS_NEOPIXEL_NUM NEOPIXEL_NUM +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3) +#define BOARD_ID "feather-esp32s3-4mbflash-2mbpsram" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define STATUS_NEOPIXEL_NUM NEOPIXEL_NUM +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3_TFT) +#define BOARD_ID "feather-esp32s3-tft" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define STATUS_NEOPIXEL_NUM NEOPIXEL_NUM +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3_REVTFT) +#define BOARD_ID "feather-esp32s3-reverse-tft" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define STATUS_NEOPIXEL_NUM NEOPIXEL_NUM +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ADAFRUIT_QTPY_ESP32S2) +#define BOARD_ID "qtpy-esp32s2" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define STATUS_NEOPIXEL_NUM 1 +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define I2c_STEMMA_WIRE1 +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM) +#define BOARD_ID "qtpy-esp32s3" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_NUM 1 +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define I2c_STEMMA_WIRE1 +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3_N4R2) +#define BOARD_ID "qtpy-esp32s3-n4r2" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define STATUS_NEOPIXEL_NUM 1 +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define I2c_STEMMA_WIRE1 +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ADAFRUIT_QTPY_ESP32C3) +#define BOARD_ID "qtpy-esp32c3" +#define USE_LITTLEFS +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define STATUS_NEOPIXEL_NUM 1 +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) +#define BOARD_ID "feather-esp8266" +#define USE_LITTLEFS +#define USE_STATUS_LED +#define STATUS_LED_PIN 0 +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ADAFRUIT_ITSYBITSY_ESP32) +#define BOARD_ID "itsybitsy-esp32" +#define USE_LITTLEFS +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define STATUS_NEOPIXEL_NUM 1 +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 +#elif defined(ARDUINO_FEATHER_ESP32) +#define BOARD_ID "feather-esp32" +#define USE_LITTLEFS +#define USE_STATUS_LED +#define STATUS_LED_PIN 13 +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ESP32_DEV) || defined(ESP32_DEV) +#define BOARD_ID "feather-esp32" +#define USE_STATUS_LED +#define STATUS_LED_PIN 13 +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2) +#define BOARD_ID "feather-esp32-v2" +#define USE_LITTLEFS +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define STATUS_NEOPIXEL_NUM 1 +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ADAFRUIT_QTPY_ESP32_PICO) +#define BOARD_ID "qtpy-esp32" +#define USE_LITTLEFS +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define STATUS_NEOPIXEL_NUM 1 +#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation +#define I2c_STEMMA_WIRE1 +#define SD_CS_PIN 33 +#elif defined(ARDUINO_RASPBERRY_PI_PICO_W) +#define BOARD_ID "rpi-pico-w" +#define USE_TINYUSB +#define USE_STATUS_LED +#define STATUS_LED_PIN 32 +#define SD_CS_PIN 33 +#elif defined(ARDUINO_RASPBERRY_PI_PICO) +#define BOARD_ID "rpi-pico" +#define USE_TINYUSB +#define USE_STATUS_LED +#define STATUS_LED_PIN LED_BUILTIN +#define SD_CS_PIN 33 +#elif defined(ARDUINO_RASPBERRY_PI_PICO_2) +#define BOARD_ID "rpi-pico-2" +#define USE_TINYUSB +#define USE_STATUS_LED +#define STATUS_LED_PIN LED_BUILTIN +#define SD_CS_PIN 33 +#elif defined(ARDUINO_ADAFRUIT_FEATHER_RP2040_ADALOGGER) +#define BOARD_ID "feather-rp2040-adalogger" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define STATUS_NEOPIXEL_NUM 1 +#define SD_USE_SPI_1 +#define SD_CS_PIN 23 +#elif defined(ARDUINO_ADAFRUIT_METRO_RP2350) +#define BOARD_ID "metro-rp2350" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define STATUS_NEOPIXEL_NUM NUM_NEOPIXEL +#define SD_USE_SPI_1 +#define SD_CS_PIN 39 +#else +#warning "Board type not identified within Wippersnapper_Boards.h!" +#endif + +#endif // ADAFRUIT_WIPPERSNAPPER_BOARDS_H diff --git a/tests/bin/offline/firmware.elf b/tests/bin/offline/firmware.elf index 21c458943..8a53779e0 100755 Binary files a/tests/bin/offline/firmware.elf and b/tests/bin/offline/firmware.elf differ diff --git a/tests/scenarios/offline/test-invalid-json.scenario.yaml b/tests/scenarios/offline/test-invalid-json.scenario.yaml index dc12905f7..474c36215 100644 --- a/tests/scenarios/offline/test-invalid-json.scenario.yaml +++ b/tests/scenarios/offline/test-invalid-json.scenario.yaml @@ -6,4 +6,4 @@ steps: - wait-serial: '[SD] Waiting for incoming JSON string...' - write-serial: '{"exportVersion":"1.0.0",' - write-serial: '\n' - - wait-serial: '[SD] Runtime Error: Unable to deserialize config.json' \ No newline at end of file + - wait-serial: '[SD] Error: Unable to deserialize config.json' \ No newline at end of file diff --git a/tests/scenarios/offline/test-log-analogin.scenario.yaml b/tests/scenarios/offline/test-log-analogin.scenario.yaml index aee02b43c..f5f4844c8 100644 --- a/tests/scenarios/offline/test-log-analogin.scenario.yaml +++ b/tests/scenarios/offline/test-log-analogin.scenario.yaml @@ -4,7 +4,7 @@ author: Brent Rubell for Adafruit Industries steps: - wait-serial: '[SD] Waiting for incoming JSON string...' - - write-serial: '{"exportVersion": "1.0.0", "exportedBy": "wokwi", "exportedAt": "2024-10-28T18:58:23.976Z", "exportedFromDevice": {"board": "metroesp32s3", "firmwareVersion": "1.0.0-beta.93", "referenceVoltage": 2.6, "totalGPIOPins": 11, "totalAnalogPins": 6}, "components": [{"componentAPI": "analogio", "name": "Analog Pin", "pinName": "D14", "type": "analog_pin", "mode": "ANALOG", "direction": "INPUT", "sampleMode": "TIMER", "analogReadMode": "raw", "period": 5, "isPin": true}], "checksum": 149}' + - write-serial: '{"exportedFromDevice":{"referenceVoltage":3.3,"totalGPIOPins":43,"totalAnalogPins":20,"statusLEDBrightness":0.5},"components":[{"name":"Analog Pin","componentAPI":"analogio","pinName":"D14","mode":"raw","direction":"INPUT","sampleMode":"TIMER","analogReadMode":"raw","period":5}],"checksum":149}' - write-serial: '\n' - wait-serial: '[analogio] Added new pin:' - wait-serial: 'Pin Name: 14' @@ -17,4 +17,4 @@ steps: control: position value: 0.5 - delay: 3s - - wait-serial: '{"timestamp":0,"pin":"A14","value":16384,"si_unit":"none"}' \ No newline at end of file + - wait-serial: '{"timestamp":1,"pin":"A14","value":16384,"si_unit":"none"}' \ No newline at end of file diff --git a/tests/scenarios/offline/test-log-digital-in.scenario.yaml b/tests/scenarios/offline/test-log-digital-in.scenario.yaml index 6471c1f52..6491f5928 100644 --- a/tests/scenarios/offline/test-log-digital-in.scenario.yaml +++ b/tests/scenarios/offline/test-log-digital-in.scenario.yaml @@ -17,4 +17,4 @@ steps: part-id: btn1 control: pressed value: 1 - - wait-serial: '{"timestamp":0,"pin":"D4","value":false,"si_unit":"boolean"}' \ No newline at end of file + - wait-serial: '{"timestamp":1,"pin":"D4","value":false,"si_unit":"boolean"}' \ No newline at end of file diff --git a/tests/scenarios/offline/test-log-ds18b20.scenario.yaml b/tests/scenarios/offline/test-log-ds18b20.scenario.yaml index 1b8148bba..72d46498f 100644 --- a/tests/scenarios/offline/test-log-ds18b20.scenario.yaml +++ b/tests/scenarios/offline/test-log-ds18b20.scenario.yaml @@ -4,7 +4,7 @@ author: Brent Rubell for Adafruit Industries steps: - wait-serial: '[SD] Waiting for incoming JSON string...' - - write-serial: '{"exportVersion": "1.0.0", "exportedBy": "wokwi", "exportedAt": "2024-10-28T18:58:23.976Z", "exportedFromDevice": {"board": "metroesp32s3", "firmwareVersion": "1.0.0-beta.93", "referenceVoltage": 2.6, "totalGPIOPins": 11, "totalAnalogPins": 6}, "components": [{"componentAPI": "ds18x20", "name": "DS18B20: Temperature Sensor", "sensorTypeCount": 2, "sensorType1": "object-temp-fahrenheit", "sensorType2": "object-temp", "pinName": "D6", "sensorResolution": 12, "period": 5}], "checksum": 34}' + - write-serial: '{"exportedFromDevice":{"referenceVoltage":2.6,"totalGPIOPins":11,"totalAnalogPins":6},"components":[{"componentAPI":"ds18x20","name":"DS18B20: Temperature Sensor","sensorTypeCount":2,"ds18x20SensorTypes":[{"type":"object-temp-fahrenheit"},{"type":"object-temp"}],"pinName":"D6","sensorResolution":12,"period":5}],"checksum":34}' - write-serial: '\n' - wait-serial: '{"timestamp":0,"pin":"D6","value":0,"si_unit":"C"}' - - wait-serial: '{"timestamp":0,"pin":"D6","value":32,"si_unit":"F"}' \ No newline at end of file + - wait-serial: '{"timestamp":1,"pin":"D6","value":32,"si_unit":"F"}' \ No newline at end of file diff --git a/tests/scenarios/offline/test-valid-checksum.scenario.yaml b/tests/scenarios/offline/test-valid-checksum.scenario.yaml index f02118e06..b7e8bf243 100644 --- a/tests/scenarios/offline/test-valid-checksum.scenario.yaml +++ b/tests/scenarios/offline/test-valid-checksum.scenario.yaml @@ -6,4 +6,4 @@ steps: - wait-serial: '[SD] Waiting for incoming JSON string...' - write-serial: '{"exportVersion": "1.0.0", "exportedBy": "wokwi", "exportedAt": "2024-10-28T18:58:23.976Z", "exportedFromDevice": {"board": "metroesp32s3", "firmwareVersion": "1.0.0-beta.93", "referenceVoltage": 2.6, "totalGPIOPins": 11, "totalAnalogPins": 6}, "components": [{"componentAPI": "analogio", "name": "Analog Pin", "pinName": "D14", "type": "analog_pin", "mode": "ANALOG", "direction": "INPUT", "sampleMode": "TIMER", "analogReadMode": "raw", "period": 5, "isPin": true}], "checksum": 28}' - write-serial: '\n' - - wait-serial: '[SD] Checksum OK!' \ No newline at end of file + - wait-serial: '[SD] Successfully deserialized JSON config file!' \ No newline at end of file