diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index fd4acbdba..15a372f29 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -2,14 +2,14 @@ name: CI on: # # Triggers the workflow on push but only for the master branch push: - branches: [master] + branches: [master, develop] paths-ignore: - "**.md" - "version.properties" # Note: This is different from "pull_request". Need to specify ref when doing checkouts. pull_request_target: - branches: [master] + branches: [master, develop] paths-ignore: - "**.md" #- "**.yml" @@ -23,26 +23,19 @@ jobs: matrix: include: - board: rak11200 - - board: tlora-v2 - board: tlora-v1 - - board: tlora_v1_3 - board: tlora-v2-1-1.6 - board: tbeam - - board: heltec-v1 - - board: heltec-v2.0 - board: heltec-v2.1 - - board: tbeam0.7 - board: meshtastic-diy-v1 - board: rak4631 - - board: rak4631_eink - board: t-echo - board: nano-g1 - board: station-g1 - - board: m5stack-core - board: m5stack-coreink - board: tbeam-s3-core # - board: pico - + runs-on: ubuntu-latest steps: - name: Checkout code @@ -96,6 +89,7 @@ jobs: - board: heltec-v2.1 - board: tbeam0.7 - board: meshtastic-diy-v1 + - board: meshtastic-dr-dev - board: nano-g1 - board: station-g1 - board: m5stack-core @@ -131,11 +125,11 @@ jobs: - name: Upgrade platformio run: | pio upgrade - + - name: Pull web ui uses: dsaltares/fetch-gh-release-asset@master with: - repo: "meshtastic/meshtastic-web" + repo: "meshtastic/web" file: "build.tar" target: "build.tar" token: ${{ secrets.GITHUB_TOKEN }} @@ -147,15 +141,15 @@ jobs: - name: Build ESP32 run: bin/build-esp32.sh ${{ matrix.board }} - + - name: Pull OTA Firmware uses: dsaltares/fetch-gh-release-asset@master with: - repo: "meshtastic/Meshtastic-OTA" + repo: "meshtastic/firmware-ota" file: "firmware.bin" target: "release/bleota.bin" token: ${{ secrets.GITHUB_TOKEN }} - + - name: Get release version string run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT id: version @@ -167,7 +161,7 @@ jobs: path: | release/*.bin release/*.elf - retention-days: 90 + retention-days: 30 build-nrf52: strategy: @@ -179,6 +173,7 @@ jobs: - board: rak4631_eink - board: t-echo - board: pca10059_diy_eink + - board: feather_diy runs-on: ubuntu-latest steps: @@ -225,7 +220,7 @@ jobs: release/*.uf2 release/*.elf release/*.zip - retention-days: 90 + retention-days: 30 build-rpi2040: strategy: @@ -279,7 +274,7 @@ jobs: path: | release/*.uf2 release/*.elf - retention-days: 90 + retention-days: 30 build-native: runs-on: ubuntu-latest @@ -338,7 +333,7 @@ jobs: release/meshtasticd_linux_amd64 release/device-*.sh release/device-*.bat - retention-days: 90 + retention-days: 30 after-checks: runs-on: ubuntu-latest @@ -369,7 +364,7 @@ jobs: id: version - name: Move files up - run: mv -b -t ./ ./*tbeam-1*/littlefs*.bin ./*tbeam-1*/bleota.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./**/meshtasticd_linux_amd64 ./*native*/*device-*.sh ./*native*/*device-*.bat + run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./**/meshtasticd_linux_amd64 ./*native*/*device-*.sh ./*native*/*device-*.bat - name: Repackage in single firmware zip uses: actions/upload-artifact@v3 @@ -392,7 +387,7 @@ jobs: # For diagnostics - name: Show artifacts run: ls -lR - + - name: Device scripts permissions run: | chmod +x ./output/device-install.sh @@ -406,7 +401,7 @@ jobs: with: name: debug-elfs-${{ steps.version.outputs.version }}.zip path: ./*.elf - retention-days: 90 + retention-days: 30 - name: Create request artifacts if: ${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request' }} @@ -427,7 +422,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 - + - name: Setup Python uses: actions/setup-python@v4 with: @@ -441,7 +436,7 @@ jobs: with: name: firmware-${{ steps.version.outputs.version }} path: ./output - + - name: Device scripts permissions run: | chmod +x ./output/device-install.sh @@ -454,7 +449,7 @@ jobs: with: name: debug-elfs-${{ steps.version.outputs.version }}.zip path: ./elfs - + - name: Zip Elfs run: zip -j -r ./debug-elfs-${{ steps.version.outputs.version }}.zip ./elfs @@ -468,7 +463,7 @@ jobs: with: draft: true prerelease: true - release_name: Meshtastic Device ${{ steps.version.outputs.version }} Alpha + release_name: Meshtastic Firmware ${{ steps.version.outputs.version }} tag_name: v${{ steps.version.outputs.version }} body: | Autogenerated by github action, developer should edit as required before publishing... @@ -498,10 +493,9 @@ jobs: - name: Bump version.properties run: >- bin/bump_version.py - + - name: Create version.properties pull request uses: peter-evans/create-pull-request@v3 with: add-paths: | version.properties - diff --git a/.gitmodules b/.gitmodules index 489f01bea..238eda7de 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "protobufs"] path = protobufs - url = https://github.com/meshtastic/Meshtastic-protobufs.git + url = https://github.com/meshtastic/protobufs.git + branch = develop diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..0ce4e3326 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM debian:bullseye-slim AS builder +RUN apt-get update +RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install wget python3 g++ zip python3-venv git vim +RUN wget https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -O get-platformio.py; chmod +x get-platformio.py +RUN python3 get-platformio.py +RUN git clone https://github.com/meshtastic/firmware --recurse-submodules +RUN cd firmware +RUN chmod +x ./firmware/bin/build-native.sh +RUN . ~/.platformio/penv/bin/activate; cd firmware; sh ./bin/build-native.sh + +FROM frolvlad/alpine-glibc +WORKDIR /root/ +COPY --from=builder /firmware/release/meshtasticd_linux_amd64 ./ +RUN apk --update add --no-cache g++ +CMD sh -cx "./meshtasticd_linux_amd64 --hwid '$RANDOM'" \ No newline at end of file diff --git a/README.md b/README.md index 39aebf9d7..6432803e4 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Meshtastic Firmware -![GitHub release downloads](https://img.shields.io/github/downloads/meshtastic/meshtastic-device/total) -[![CI](https://img.shields.io/github/workflow/status/meshtastic/Meshtastic-device/CI?label=actions&logo=github&color=yellow)](https://github.com/meshtastic/repo/actions/workflows/main_matrix.yml) -[![CLA assistant](https://cla-assistant.io/readme/badge/meshtastic/Meshtastic-device)](https://cla-assistant.io/meshtastic/Meshtastic-device) +![GitHub release downloads](https://img.shields.io/github/downloads/meshtastic/firmware/total) +[![CI](https://img.shields.io/github/workflow/status/meshtastic/firmware/CI?label=actions&logo=github&color=yellow)](https://github.com/meshtastic/firmware/actions/workflows/main_matrix.yml) +[![CLA assistant](https://cla-assistant.io/readme/badge/meshtastic/firmware)](https://cla-assistant.io/meshtastic/firmware) [![Fiscal Contributors](https://opencollective.com/meshtastic/tiers/badge.svg?label=Fiscal%20Contributors&color=deeppink)](https://opencollective.com/meshtastic/) [![Vercel](https://img.shields.io/static/v1?label=Powered%20by&message=Vercel&style=flat&logo=vercel&color=000000)](https://vercel.com?utm_source=meshtastic&utm_campaign=oss) @@ -10,10 +10,9 @@ This repository contains the device firmware for the Meshtastic project. - **[Building Instructions](https://meshtastic.org/docs/developers/Firmware/build)** **[Flashing Instructions](https://meshtastic.org/docs/getting-started/flashing-firmware/)** ## Stats -![Alt](https://repobeats.axiom.co/api/embed/99a2cf5622bb4807f9e8c3b86589f1133cce58a2.svg 'Repobeats analytics image') +![Alt](https://repobeats.axiom.co/api/embed/a92f097d9197ae853e780ec53d7d126e545629ab.svg "Repobeats analytics image") diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini index 798fb3d5a..ba98a6b1f 100644 --- a/arch/esp32/esp32.ini +++ b/arch/esp32/esp32.ini @@ -3,7 +3,7 @@ extends = arduino_base platform = platformio/espressif32@^5.2.0 build_src_filter = - ${arduino_base.build_src_filter} - - - + ${arduino_base.build_src_filter} - - - - upload_speed = 921600 debug_init_break = tbreak setup monitor_filters = esp32_exception_decoder @@ -33,8 +33,7 @@ lib_deps = ${environmental_base.lib_deps} https://github.com/meshtastic/esp32_https_server.git#657509856ce97e9dddeffb89a559f544faefd5cd h2zero/NimBLE-Arduino@^1.4.0 - arduino-libraries/NTPClient@^3.1.0 - https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 + https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 lib_ignore = segger_rtt diff --git a/arch/esp32/esp32s3.ini b/arch/esp32/esp32s3.ini index 8dc6d0b62..f5338d9a9 100644 --- a/arch/esp32/esp32s3.ini +++ b/arch/esp32/esp32s3.ini @@ -2,7 +2,7 @@ extends = arduino_base platform = platformio/espressif32@^5.2.0 build_src_filter = - ${arduino_base.build_src_filter} - - - + ${arduino_base.build_src_filter} - - - - upload_speed = 961200 monitor_speed = 115200 debug_init_break = tbreak setup @@ -33,7 +33,6 @@ lib_deps = ${environmental_base.lib_deps} https://github.com/meshtastic/esp32_https_server.git#657509856ce97e9dddeffb89a559f544faefd5cd h2zero/NimBLE-Arduino@^1.4.0 - arduino-libraries/NTPClient@^3.1.0 https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 lib_ignore = diff --git a/arch/nrf52/nrf52.ini b/arch/nrf52/nrf52.ini index f4e2af236..46f946530 100644 --- a/arch/nrf52/nrf52.ini +++ b/arch/nrf52/nrf52.ini @@ -8,7 +8,7 @@ build_flags = ${arduino_base.build_flags} -Wno-unused-variable -Isrc/platform/nrf52 build_src_filter = - ${arduino_base.build_src_filter} - - - - - - - - + ${arduino_base.build_src_filter} - - - - - - - - - lib_ignore = BluetoothOTA diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index eb65322d4..b61071007 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -7,7 +7,8 @@ build_src_filter = - - - - - + - + - - - +<../variants/portduino> diff --git a/arch/rp2040/rp2040.ini b/arch/rp2040/rp2040.ini index 9eea340bf..8b7bdbff9 100644 --- a/arch/rp2040/rp2040.ini +++ b/arch/rp2040/rp2040.ini @@ -10,7 +10,7 @@ build_flags = -D__PLAT_RP2040__ # -D _POSIX_THREADS build_src_filter = - ${arduino_base.build_src_filter} - - - - - - - - + ${arduino_base.build_src_filter} - - - - - - - - - lib_ignore = BluetoothOTA lib_deps = diff --git a/arch/stm32/stm32wl5e.ini b/arch/stm32/stm32wl5e.ini index d13750fdb..3fc7583ad 100644 --- a/arch/stm32/stm32wl5e.ini +++ b/arch/stm32/stm32wl5e.ini @@ -10,7 +10,7 @@ build_flags = # Arduino/PlatformIO framework-arduinoststm32 package does not presently have SUBGHZSPI support # -DPIN_SPI_MOSI=PINSUBGHZSPIMOSI -DPIN_SPI_MISO=PINSUBGHZSPIMISO -DPIN_SPI_SCK=PINSUBGHZSPISCK build_src_filter = - ${arduino_base.build_src_filter} - - - - - - - - - - - - - + ${arduino_base.build_src_filter} - - - - - - - - - - - - - - lib_deps = ${env.lib_deps} https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b diff --git a/bin/build-all.sh.legacy b/bin/build-all.sh.legacy deleted file mode 100755 index 55c151da1..000000000 --- a/bin/build-all.sh.legacy +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env bash - -set -e - -VERSION=`bin/buildinfo.py long` -SHORT_VERSION=`bin/buildinfo.py short` - -BOARDS_ESP32="rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 nano-g1 station-g1 m5stack-core m5stack-coreink" -#BOARDS_ESP32=tbeam - -# FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine -BOARDS_NRF52="rak4631 rak4631_eink t-echo pca10059_diy_eink" -#BOARDS_NRF52="" - -OUTDIR=release/latest - -# We keep all old builds (and their map files in the archive dir) -ARCHIVEDIR=release/archive - -rm -f $OUTDIR/firmware* - -mkdir -p $OUTDIR/bins $ARCHIVEDIR -rm -r $OUTDIR/bins/* || true -mkdir -p $OUTDIR/bins/universal $OUTDIR/elfs/universal - -# build the named environment and copy the bins to the release directory -function do_build() { - BOARD=$1 - isNrf=$3 - - echo "Building for $BOARD ($isNrf) with $PLATFORMIO_BUILD_FLAGS" - rm -f .pio/build/$BOARD/firmware.* - - # The shell vars the build tool expects to find - export APP_VERSION=$VERSION - - basename=universal/firmware-$BOARD-$VERSION - - pio run --environment $BOARD # -v - SRCELF=.pio/build/$BOARD/firmware.elf - cp $SRCELF $OUTDIR/elfs/$basename.elf - - if [ "$isNrf" = "false" ] - then - echo "Copying ESP32 bin file" - SRCBIN=.pio/build/$BOARD/firmware.bin - cp $SRCBIN $OUTDIR/bins/$basename.bin - else - echo "Generating NRF52 uf2 file" - SRCHEX=.pio/build/$BOARD/firmware.hex - bin/uf2conv.py $SRCHEX -c -o $OUTDIR/bins/$basename.uf2 -f 0xADA52840 - fi -} - -function do_boards() { - declare boards=$1 - declare isNrf=$2 - for board in $boards; do - # Build universal - echo "about to build $board $isNrf" - do_build $board "" "$isNrf" - done -} - -# Make sure our submodules are current -git submodule update - -# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale -platformio lib update - -do_boards "$BOARDS_ESP32" "false" -do_boards "$BOARDS_NRF52" "true" - -pio run --environment native -cp .pio/build/native/program $OUTDIR/bins/universal/meshtasticd_linux_amd64 - -echo "Building Filesystem for ESP32 targets" -pio run --environment tbeam -t buildfs -cp .pio/build/tbeam/spiffs.bin $OUTDIR/bins/universal/littlefs-$VERSION.bin - -# keep the bins in archive also -cp $OUTDIR/bins/universal/littlefs* $OUTDIR/bins/universal/firmware* $OUTDIR/elfs/universal/firmware* $ARCHIVEDIR - -echo Updating android bins $OUTDIR/forandroid -rm -rf $OUTDIR/forandroid -mkdir -p $OUTDIR/forandroid -cp -a $OUTDIR/bins/universal/*.bin $OUTDIR/forandroid/ - -cat >$OUTDIR/curfirmwareversion.xml < - - - - - $VERSION - $SHORT_VERSION - -XML - -echo Generating $ARCHIVEDIR/firmware-$VERSION.zip -rm -f $ARCHIVEDIR/firmware-$VERSION.zip -zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $ARCHIVEDIR/littlefs-$VERSION.bin $OUTDIR/bins/universal/firmware-*-$VERSION.* $OUTDIR/bins/universal/meshtasticd* images/system-info.bin bin/device-install.* bin/device-update.* -echo Generating $ARCHIVEDIR/elfs-$VERSION.zip -rm -f $ARCHIVEDIR/elfs-$VERSION.zip -zip --junk-paths $ARCHIVEDIR/elfs-$VERSION.zip $OUTDIR/elfs/universal/firmware-*-$VERSION.* - -echo BUILT ALL diff --git a/bin/build-esp32.sh b/bin/build-esp32.sh index 40a6c3aee..12961864f 100755 --- a/bin/build-esp32.sh +++ b/bin/build-esp32.sh @@ -14,7 +14,7 @@ rm -r $OUTDIR/* || true git submodule update # Important to pull latest version of libs into all device flavors, otherwise some devices might be stale -platformio lib update +platformio pkg update echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS" rm -f .pio/build/$1/firmware.* diff --git a/bin/build-native.sh b/bin/build-native.sh index 31ef01155..b620a01d8 100755 --- a/bin/build-native.sh +++ b/bin/build-native.sh @@ -16,7 +16,7 @@ rm -r $OUTDIR/* || true git submodule update # Important to pull latest version of libs into all device flavors, otherwise some devices might be stale -platformio lib update +platformio pkg update pio run --environment native cp .pio/build/native/program $OUTDIR/meshtasticd_linux_amd64 diff --git a/bin/build-nrf52.sh b/bin/build-nrf52.sh index 76972b100..6c723e28f 100755 --- a/bin/build-nrf52.sh +++ b/bin/build-nrf52.sh @@ -14,7 +14,7 @@ rm -r $OUTDIR/* || true git submodule update # Important to pull latest version of libs into all device flavors, otherwise some devices might be stale -platformio lib update +platformio pkg update echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS" rm -f .pio/build/$1/firmware.* diff --git a/bin/build-rpi2040.sh b/bin/build-rpi2040.sh index 04fe7106b..670f570f1 100755 --- a/bin/build-rpi2040.sh +++ b/bin/build-rpi2040.sh @@ -14,7 +14,7 @@ rm -r $OUTDIR/* || true git submodule update # Important to pull latest version of libs into all device flavors, otherwise some devices might be stale -platformio lib update +platformio pkg update echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS" rm -f .pio/build/$1/firmware.* diff --git a/bin/promote-release.sh b/bin/promote-release.sh index b9380b02b..f96d2a568 100755 --- a/bin/promote-release.sh +++ b/bin/promote-release.sh @@ -9,9 +9,6 @@ VERSION=`bin/buildinfo.py long` # Must have a V prefix to trigger github git tag "v${VERSION}" -# Commented out per https://github.com/meshtastic/Meshtastic-device/issues/947 -#git push root "v${VERSION}" # push the tag - git push origin "v${VERSION}" # push the tag echo "Tag ${VERSION} pushed to github, github actions should now be building the draft release. If it seems good, click to publish it" diff --git a/bin/regen-protos.sh b/bin/regen-protos.sh index 9c16591e3..2734c213b 100755 --- a/bin/regen-protos.sh +++ b/bin/regen-protos.sh @@ -3,7 +3,7 @@ set -e echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.6 to be located in the" -echo "meshtastic-device root directory if the following step fails, you should download the correct" +echo "firmware root directory if the following step fails, you should download the correct" echo "prebuilt binaries for your computer into nanopb-0.4.6" # the nanopb tool seems to require that the .options file be in the current directory! diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..f137139c2 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +version: "3.7" + +services: + meshtastic-node: + build: . + deploy: + mode: replicated + replicas: 80 + networks: + - mesh + +networks: + mesh: \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 1f97cfb19..0021350dd 100644 --- a/platformio.ini +++ b/platformio.ini @@ -22,6 +22,7 @@ ;default_envs = pca10059_diy_eink ;default_envs = meshtastic-diy-v1 ;default_envs = meshtastic-diy-v1.1 +;default_envs = meshtastic-dr-dev ;default_envs = m5stack-coreink ;default_envs = rak4631 @@ -58,8 +59,8 @@ lib_deps = check_tool = cppcheck check_skip_packages = yes check_flags = - --common-flag - cppcheck: --enable=--inline-suppr + -DAPP_VERSION=1.0.0 + --suppressions-list=suppressions.txt ; Common settings for conventional (non Portduino) Arduino targets [arduino_base] @@ -68,7 +69,7 @@ lib_deps = ${env.lib_deps} ; Portduino is using meshtastic fork for now jgromes/RadioLib@5.4.1 - https://github.com/caveman99/SparkFun_ATECCX08a_Arduino_Library.git#008e7f9d40bad66b2f7a0074aaac05b7c424339d + https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#52b5282639d08a8cbd4b748363089eed6102dc76 build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0 @@ -79,6 +80,7 @@ build_src_filter = ${env.build_src_filter} - [networking_base] lib_deps = knolleary/PubSubClient@^2.8 + arduino-libraries/NTPClient@^3.1.0 meshtastic/json11@^1.0.2 ; Common libs for environmental measurements in telemetry module diff --git a/protobufs b/protobufs index d0559bfa3..5b892e4c1 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit d0559bfa3c31023ed2f2aa3807b6a0a1da9a6feb +Subproject commit 5b892e4c196f8620f2009cdef219eb2c237cc636 diff --git a/src/ButtonThread.h b/src/ButtonThread.h index af0a8e1ec..088642099 100644 --- a/src/ButtonThread.h +++ b/src/ButtonThread.h @@ -159,21 +159,16 @@ class ButtonThread : public concurrency::OSThread static void userButtonDoublePressed() { -#ifdef ARCH_ESP32 - disablePin(); -#elif defined(USE_EINK) +#if defined(USE_EINK) && defined(PIN_EINK_EN) digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW); #endif } static void userButtonMultiPressed() { -#ifdef ARCH_ESP32 - clearNVS(); -#endif -#ifdef ARCH_NRF52 - clearBonds(); -#endif + screen->print("Sent ad-hoc ping\n"); + service.refreshMyNodeInfo(); + service.sendNetworkPing(NODENUM_BROADCAST, true); } static void userButtonPressedLongStart() diff --git a/src/Power.cpp b/src/Power.cpp index d3782a2a4..af10acb5e 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -233,11 +233,14 @@ bool Power::setup() void Power::shutdown() { - + screen->setOn(false); +#if defined(USE_EINK) && defined(PIN_EINK_EN) + digitalWrite(PIN_EINK_EN, LOW); //power off backlight first +#endif #ifdef HAS_PMU DEBUG_MSG("Shutting down\n"); - if(PMU){ + if(PMU) { PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF); PMU->shutdown(); } @@ -312,7 +315,7 @@ int32_t Power::runOnce() #ifdef HAS_PMU // WE no longer use the IRQ line to wake the CPU (due to false wakes from sleep), but we do poll // the IRQ status by reading the registers over I2C - if(PMU){ + if(PMU) { PMU->getIrqStatus(); @@ -341,10 +344,11 @@ int32_t Power::runOnce() if (PMU->isBatRemoveIrq()) { DEBUG_MSG("Battery removed\n"); } - if (PMU->isPekeyShortPressIrq()) { - DEBUG_MSG("PEK short button press\n"); - } */ + if (PMU->isPekeyLongPressIrq()) { + DEBUG_MSG("PEK long button press\n"); + screen->setOn(false); + } PMU->clearIrqStatus(); } @@ -451,7 +455,6 @@ bool Power::axpChipInit() // Set constant current charging current PMU->setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_450MA); - } else if (PMU->getChipModel() == XPOWERS_AXP2101) { // t-beam s3 core diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index c16f52592..dd3992a14 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -337,7 +337,7 @@ void PowerFSM_setup() #ifdef ARCH_ESP32 // We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally) - // See: https://github.com/meshtastic/Meshtastic-device/issues/1071 + // See: https://github.com/meshtastic/firmware/issues/1071 if (isRouter || config.power.is_power_saving) { powerFSM.add_timed_transition(&stateNB, &stateLS, getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL, "Min wake timeout"); powerFSM.add_timed_transition(&stateDARK, &stateLS, getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs), NULL, "Bluetooth timeout"); diff --git a/src/RedirectablePrint.cpp b/src/RedirectablePrint.cpp index de9b95027..66c83171a 100644 --- a/src/RedirectablePrint.cpp +++ b/src/RedirectablePrint.cpp @@ -44,11 +44,9 @@ size_t RedirectablePrint::vprintf(const char *format, va_list arg) static char printBuf[160]; va_copy(copy, arg); - int len = vsnprintf(printBuf, sizeof(printBuf), format, copy); + size_t len = vsnprintf(printBuf, sizeof(printBuf), format, copy); va_end(copy); - if (len < 0) return 0; - // If the resulting string is longer than sizeof(printBuf)-1 characters, the remaining characters are still counted for the return value if (len > sizeof(printBuf) - 1) { diff --git a/src/buzz/buzz.cpp b/src/buzz/buzz.cpp index 059630bfe..f8314fe51 100644 --- a/src/buzz/buzz.cpp +++ b/src/buzz/buzz.cpp @@ -1,5 +1,6 @@ #include "buzz.h" #include "configuration.h" +#include "NodeDB.h" #ifndef PIN_BUZZER @@ -42,17 +43,19 @@ const int DURATION_1_8 = 125; // 1/8 note const int DURATION_1_4 = 250; // 1/4 note void playTones(const ToneDuration *tone_durations, int size) { - for (int i = 0; i < size; i++) { - const auto &tone_duration = tone_durations[i]; + if (config.network.eth_enabled != true) { + for (int i = 0; i < size; i++) { + const auto &tone_duration = tone_durations[i]; #ifdef M5STACK - Tone.tone(tone_duration.frequency_khz); - delay(tone_duration.duration_ms); - Tone.mute(); + Tone.tone(tone_duration.frequency_khz); + delay(tone_duration.duration_ms); + Tone.mute(); #else - tone(PIN_BUZZER, tone_duration.frequency_khz, tone_duration.duration_ms); + tone(PIN_BUZZER, tone_duration.frequency_khz, tone_duration.duration_ms); #endif - // to distinguish the notes, set a minimum time between them. - delay(1.3 * tone_duration.duration_ms); + // to distinguish the notes, set a minimum time between them. + delay(1.3 * tone_duration.duration_ms); + } } } diff --git a/src/configuration.h b/src/configuration.h index 9374c29d4..4b157611d 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -142,6 +142,9 @@ along with this program. If not, see . #ifndef HAS_WIFI #define HAS_WIFI 0 #endif +#ifndef HAS_ETHERNET + #define HAS_ETHERNET 0 +#endif #ifndef HAS_SCREEN #define HAS_SCREEN 0 #endif @@ -163,6 +166,12 @@ along with this program. If not, see . #ifndef HAS_RTC #define HAS_RTC 0 #endif +#ifndef HAS_CPU_SHUTDOWN + #define HAS_CPU_SHUTDOWN 0 +#endif +#ifndef HAS_BLUETOOTH + #define HAS_BLUETOOTH 0 +#endif #include "RF95Configuration.h" #include "DebugConfiguration.h" diff --git a/src/gps/NMEAWPL.cpp b/src/gps/NMEAWPL.cpp index 95e69343b..222a2d04c 100644 --- a/src/gps/NMEAWPL.cpp +++ b/src/gps/NMEAWPL.cpp @@ -15,11 +15,11 @@ * ------------------------------------------- */ -uint printWPL(char *buf, const Position &pos, const char *name) +uint32_t printWPL(char *buf, const Position &pos, const char *name) { - uint len = sprintf(buf, "$GNWPL,%07.2f,%c,%08.2f,%c,%s", pos.latitude_i * 1e-5, pos.latitude_i < 0 ? 'S' : 'N', pos.longitude_i * 1e-5, pos.longitude_i < 0 ? 'W' : 'E', name); - uint chk = 0; - for (uint i = 1; i < len; i++) { + uint32_t len = sprintf(buf, "$GNWPL,%07.2f,%c,%08.2f,%c,%s", pos.latitude_i * 1e-5, pos.latitude_i < 0 ? 'S' : 'N', pos.longitude_i * 1e-5, pos.longitude_i < 0 ? 'W' : 'E', name); + uint32_t chk = 0; + for (uint32_t i = 1; i < len; i++) { chk ^= buf[i]; } len += sprintf(buf + len, "*%02X\r\n", chk); @@ -50,9 +50,9 @@ uint printWPL(char *buf, const Position &pos, const char *name) * ------------------------------------------- */ -uint printGGA(char *buf, const Position &pos) +uint32_t printGGA(char *buf, const Position &pos) { - uint len = sprintf(buf, "$GNGGA,%06u.%03u,%07.2f,%c,%08.2f,%c,%u,%02u,%04u,%04d,%c,%04d,%c,%d,%04d", + uint32_t len = sprintf(buf, "$GNGGA,%06u.%03u,%07.2f,%c,%08.2f,%c,%u,%02u,%04u,%04d,%c,%04d,%c,%d,%04d", pos.time / 1000, pos.time % 1000, pos.latitude_i * 1e-5, pos.latitude_i < 0 ? 'S' : 'N', @@ -67,10 +67,10 @@ uint printGGA(char *buf, const Position &pos) 0, 0); - uint chk = 0; - for (uint i = 1; i < len; i++) { + uint32_t chk = 0; + for (uint32_t i = 1; i < len; i++) { chk ^= buf[i]; } len += sprintf(buf + len, "*%02X\r\n", chk); return len; -} \ No newline at end of file +} diff --git a/src/gps/NMEAWPL.h b/src/gps/NMEAWPL.h index 853c850eb..aaa18933c 100644 --- a/src/gps/NMEAWPL.h +++ b/src/gps/NMEAWPL.h @@ -3,5 +3,5 @@ #include #include "main.h" -uint printWPL(char *buf, const Position &pos, const char *name); -uint printGGA(char *buf, const Position &pos); +uint32_t printWPL(char *buf, const Position &pos, const char *name); +uint32_t printGGA(char *buf, const Position &pos); diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp index 9062fc018..9e0834954 100644 --- a/src/graphics/EInkDisplay2.cpp +++ b/src/graphics/EInkDisplay2.cpp @@ -14,8 +14,8 @@ #define TECHO_DISPLAY_MODEL GxEPD2_154_D67 #elif defined(RAK4630) -//GxEPD2_213_B74 - RAK14000 2.13 inch b/w 250x128 -#define TECHO_DISPLAY_MODEL GxEPD2_213_B74 +//GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 - changed from GxEPD2_213_B74 - which was not going to give partial update support +#define TECHO_DISPLAY_MODEL GxEPD2_213_BN //4.2 inch 300x400 - GxEPD2_420_M01 //#define TECHO_DISPLAY_MODEL GxEPD2_420_M01 @@ -46,9 +46,9 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl) setGeometry(GEOMETRY_RAWMODE, TECHO_DISPLAY_MODEL::WIDTH, TECHO_DISPLAY_MODEL::HEIGHT); #elif defined(RAK4630) - //GxEPD2_213_B74 - RAK14000 2.13 inch b/w 250x128 + //GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 setGeometry(GEOMETRY_RAWMODE, 250, 122); - + //GxEPD2_420_M01 //setGeometry(GEOMETRY_RAWMODE, 300, 400); @@ -110,14 +110,17 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit) adafruitDisplay->display(false); // FIXME, use partial update mode #elif defined(RAK4630) - //RAK14000 2.13 inch b/w 250x122 does not support partial updates - adafruitDisplay->display(false); // FIXME, use partial update mode + //RAK14000 2.13 inch b/w 250x122 actually now does support partial updates + + //Full update mode (slow) + //adafruitDisplay->display(false); // FIXME, use partial update mode //Only enable for e-Paper with support for partial updates and comment out above adafruitDisplay->display(false); // 1.54 inch 200x200 - GxEPD2_154_M09 + // 2.13 inch 250x122 - GxEPD2_213_BN // 2.9 inch 296x128 - GxEPD2_290_T5D // 4.2 inch 300x400 - GxEPD2_420_M01 - //adafruitDisplay->nextPage(); + adafruitDisplay->nextPage(); #elif defined(PCA10059) || defined(M5_COREINK) adafruitDisplay->nextPage(); @@ -190,11 +193,11 @@ bool EInkDisplay::connect() adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0)); - //RAK14000 2.13 inch b/w 250x122 does not support partial updates + //RAK14000 2.13 inch b/w 250x122 does actually now support partial updates adafruitDisplay->setRotation(3); - //For 1.54, 2.9 and 4.2 + //Partial update support for 1.54, 2.13 RAK14000 b/w , 2.9 and 4.2 //adafruitDisplay->setRotation(1); - //adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight); + adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight); } else { (void)adafruitDisplay; } diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 0f6c96f0f..d6e90c6f9 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -50,8 +50,6 @@ along with this program. If not, see . using namespace meshtastic; /** @todo remove */ -extern bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct); - namespace graphics { @@ -67,6 +65,8 @@ namespace graphics static FrameCallback normalFrames[MAX_NUM_NODES + NUM_EXTRA_FRAMES]; static uint32_t targetFramerate = IDLE_FRAMERATE; static char btPIN[16] = "888888"; + +uint32_t logo_timeout = 5000; // 4 seconds for EACH logo // This image definition is here instead of images.h because it's modified dynamically by the drawBattery function uint8_t imgBattery[16] = {0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xE7, 0x3C}; @@ -944,6 +944,9 @@ void Screen::setup() // Set the utf8 conversion function dispdev.setFontTableLookupFunction(customFontTableLookup); + if (strlen(oemStore.oem_text) > 0) + logo_timeout *= 2; + // Add frames. static FrameCallback bootFrames[] = {drawBootScreen}; static const int bootFrameCount = sizeof(bootFrames) / sizeof(bootFrames[0]); @@ -1012,26 +1015,28 @@ int32_t Screen::runOnce() return RUN_SAME; } - // Show boot screen for first 5 seconds, then switch to normal operation. + // Show boot screen for first logo_timeout seconds, then switch to normal operation. // serialSinceMsec adjusts for additional serial wait time during nRF52 bootup static bool showingBootScreen = true; - if (showingBootScreen && (millis() > (5000 + serialSinceMsec))) { + if (showingBootScreen && (millis() > (logo_timeout + serialSinceMsec))) { DEBUG_MSG("Done with boot screen...\n"); stopBootScreen(); showingBootScreen = false; } - // If we have an OEM Boot screen, toggle after 2,5 seconds + // If we have an OEM Boot screen, toggle after logo_timeout seconds if (strlen(oemStore.oem_text) > 0) { static bool showingOEMBootScreen = true; - if (showingOEMBootScreen && (millis() > (2500 + serialSinceMsec))) { + if (showingOEMBootScreen && (millis() > ((logo_timeout / 2) + serialSinceMsec))) { DEBUG_MSG("Switch to OEM screen...\n"); // Change frames. static FrameCallback bootOEMFrames[] = {drawOEMBootScreen}; static const int bootOEMFrameCount = sizeof(bootOEMFrames) / sizeof(bootOEMFrames[0]); ui.setFrames(bootOEMFrames, bootOEMFrameCount); ui.update(); +#ifndef USE_EINK ui.update(); +#endif showingOEMBootScreen = false; } } @@ -1390,7 +1395,6 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i { #if HAS_WIFI const char *wifiName = config.network.wifi_ssid; - const char *wifiPsw = config.network.wifi_psk; displayedNodeNum = 0; // Not currently showing a node pane @@ -1399,11 +1403,7 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i // The coordinates define the left starting point of the text display->setTextAlignment(TEXT_ALIGN_LEFT); - if (isSoftAPForced()) { - display->drawString(x, y, String("WiFi: Software AP (Admin)")); - } else if (config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN) { - display->drawString(x, y, String("WiFi: Software AP")); - } else if (WiFi.status() != WL_CONNECTED) { + if (WiFi.status() != WL_CONNECTED) { display->drawString(x, y, String("WiFi: Not Connected")); } else { display->drawString(x, y, String("WiFi: Connected")); @@ -1424,25 +1424,14 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i - WL_NO_SHIELD: assigned when no WiFi shield is present; */ - if (WiFi.status() == WL_CONNECTED || isSoftAPForced() || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN) { - if (config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN || isSoftAPForced()) { - display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.softAPIP().toString().c_str())); - - // Number of connections to the AP. Default max for the esp32 is 4 - display->drawString(x + SCREEN_WIDTH - display->getStringWidth("(" + String(WiFi.softAPgetStationNum()) + "/4)"), - y + FONT_HEIGHT_SMALL * 1, "(" + String(WiFi.softAPgetStationNum()) + "/4)"); - } else { - display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.localIP().toString().c_str())); - } - + if (WiFi.status() == WL_CONNECTED) { + display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.localIP().toString().c_str())); } else if (WiFi.status() == WL_NO_SSID_AVAIL) { display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "SSID Not Found"); } else if (WiFi.status() == WL_CONNECTION_LOST) { display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Lost"); } else if (WiFi.status() == WL_CONNECT_FAILED) { display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Failed"); - //} else if (WiFi.status() == WL_DISCONNECTED) { - // display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Disconnected"); } else if (WiFi.status() == WL_IDLE_STATUS) { display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Idle ... Reconnecting"); } else { @@ -1509,24 +1498,8 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i } } - if (isSoftAPForced()) { - if ((millis() / 10000) % 2) { - display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: meshtasticAdmin"); - } else { - display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "PWD: 12345678"); - } + display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName)); - } else { - if (config.network.wifi_mode== Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN) { - if ((millis() / 10000) % 2) { - display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName)); - } else { - display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "PWD: " + String(wifiPsw)); - } - } else { - display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName)); - } - } display->drawString(x, y + FONT_HEIGHT_SMALL * 3, "http://meshtastic.local"); /* Display a heartbeat pixel that blinks every time the frame is redrawn */ diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index ab8d44430..23828b3ee 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -10,7 +10,7 @@ namespace graphics class Screen { public: - Screen(char){} + explicit Screen(char){} void onPress() {} void setup() {} void setOn(bool) {} @@ -131,8 +131,7 @@ class Screen : public concurrency::OSThread void setOn(bool on) { if (!on) - handleSetOn( - false); // We handle off commands immediately, because they might be called because the CPU is shutting down + handleSetOn(false); // We handle off commands immediately, because they might be called because the CPU is shutting down else enqueueCmd(ScreenCmd{.cmd = on ? Cmd::SET_ON : Cmd::SET_OFF}); } diff --git a/src/main.cpp b/src/main.cpp index d4d76cc3b..b6657b7a4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,22 +30,28 @@ // #include #include "mesh/http/WiFiAPClient.h" +#include "mesh/eth/ethClient.h" #ifdef ARCH_ESP32 #include "mesh/http/WebServer.h" #include "nimble/NimbleBluetooth.h" #endif -#if HAS_WIFI || defined(ARCH_PORTDUINO) +#if HAS_WIFI #include "mesh/wifi/WiFiServerAPI.h" #include "mqtt/MQTT.h" #endif +#if HAS_ETHERNET +#include "mesh/eth/ethServerAPI.h" +#include "mqtt/MQTT.h" +#endif + #include "LLCC68Interface.h" #include "RF95Interface.h" #include "SX1262Interface.h" #include "SX1268Interface.h" -#include "SX1281Interface.h" +#include "SX1280Interface.h" #if !HAS_RADIO && defined(ARCH_PORTDUINO) #include "platform/portduino/SimRadio.h" #endif @@ -191,8 +197,6 @@ void setup() digitalWrite(RESET_OLED, 1); #endif - bool forceSoftAP = 0; - #ifdef BUTTON_PIN #ifdef ARCH_ESP32 @@ -205,12 +209,6 @@ void setup() delay(10); #endif - // BUTTON_PIN is pulled high by a 12k resistor. - if (!digitalRead(BUTTON_PIN)) { - forceSoftAP = 1; - DEBUG_MSG("Setting forceSoftAP = 1\n"); - } - #endif #endif @@ -242,6 +240,12 @@ void setup() delay(1); #endif +#ifdef RAK4630 + // We need to enable 3.3V periphery in order to scan it + pinMode(PIN_3V3_EN, OUTPUT); + digitalWrite(PIN_3V3_EN, 1); +#endif + // We need to scan here to decide if we have a screen for nodeDB.init() // In T-Beam-S3-core, the I2C device cannot be scanned before power initialization, otherwise the device will be stuck if ((HW_VENDOR != HardwareModel_LILYGO_TBEAM_S3_CORE)) { @@ -276,11 +280,12 @@ void setup() #ifdef ARCH_NRF52 nrf52Setup(); #endif - playStartMelody(); // We do this as early as possible because this loads preferences from flash // but we need to do this after main cpu iniot (esp32setup), because we need the random seed set nodeDB.init(); + playStartMelody(); + // Currently only the tbeam has a PMU power = new Power(); power->setStatusHandler(powerStatus); @@ -292,6 +297,10 @@ void setup() * Boards with an PMU need to be powered on to correctly scan to the device address, such as t-beam-s3-core */ scanI2Cdevice(); + + // fixed screen override? + if (config.display.oled != Config_DisplayConfig_OledType_OLED_AUTO) + screen_model = config.display.oled; // Init our SPI controller (must be before screen and lora) initSPI(); @@ -371,15 +380,15 @@ void setup() } #endif -#if defined(USE_SX1281) && !defined(ARCH_PORTDUINO) +#if defined(USE_SX1280) && !defined(ARCH_PORTDUINO) if (!rIf) { - rIf = new SX1281Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI); + rIf = new SX1280Interface(SX128X_CS, SX128X_DIO1, SX128X_RESET, SX128X_BUSY, SPI); if (!rIf->init()) { - DEBUG_MSG("Warning: Failed to find SX1281 radio\n"); + DEBUG_MSG("Warning: Failed to find SX1280 radio\n"); delete rIf; rIf = NULL; } else { - DEBUG_MSG("SX1281 Radio init succeeded, using SX1281 radio\n"); + DEBUG_MSG("SX1280 Radio init succeeded, using SX1280 radio\n"); rIf_wide_lora = true; } } @@ -437,12 +446,17 @@ void setup() } #endif -#if HAS_WIFI +#if HAS_WIFI || HAS_ETHERNET mqttInit(); #endif +#ifndef ARCH_PORTDUINO // Initialize Wifi - initWifi(forceSoftAP); + initWifi(); + + // Initialize Ethernet + initEthernet(); +#endif #ifdef ARCH_ESP32 // Start web server thread. diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index 200184720..9ae211e6e 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -79,7 +79,7 @@ void Channels::initDefaultChannel(ChannelIndex chIndex) Config_LoRaConfig &loraConfig = config.lora; loraConfig.modem_preset = Config_LoRaConfig_ModemPreset_LONG_FAST; // Default to Long Range & Fast - + loraConfig.use_preset = true; loraConfig.tx_power = 0; // default uint8_t defaultpskIndex = 1; channelSettings.psk.bytes[0] = defaultpskIndex; @@ -218,9 +218,7 @@ const char *Channels::getName(size_t chIndex) // Per mesh.proto spec, if bandwidth is specified we must ignore modemPreset enum, we assume that in that case // the app fucked up and forgot to set channelSettings.name - if (config.lora.bandwidth != 0) - channelName = "Custom"; - else + if (config.lora.use_preset) { switch (config.lora.modem_preset) { case Config_LoRaConfig_ModemPreset_SHORT_SLOW: channelName = "ShortSlow"; @@ -247,6 +245,10 @@ const char *Channels::getName(size_t chIndex) channelName = "Invalid"; break; } + } + else { + channelName = "Custom"; + } } return channelName; @@ -265,7 +267,7 @@ their nodes * * This function will also need to be implemented in GUI apps that talk to the radio. * -* https://github.com/meshtastic/Meshtastic-device/issues/269 +* https://github.com/meshtastic/firmware/issues/269 */ const char *Channels::getPrimaryName() { diff --git a/src/mesh/Channels.h b/src/mesh/Channels.h index 5c5af0ec2..ebf08d32c 100644 --- a/src/mesh/Channels.h +++ b/src/mesh/Channels.h @@ -74,7 +74,7 @@ class Channels * * This function will also need to be implemented in GUI apps that talk to the radio. * - * https://github.com/meshtastic/Meshtastic-device/issues/269 + * https://github.com/meshtastic/firmware/issues/269 */ const char *getPrimaryName(); diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index b6519abdb..818bacf45 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -29,8 +29,8 @@ bool FloodingRouter::shouldFilterReceived(MeshPacket *p) void FloodingRouter::sniffReceived(const MeshPacket *p, const Routing *c) { - PacketId ackId = ((c && c->error_reason == Routing_Error_NONE) || !c) ? p->decoded.request_id : 0; - if (ackId && p->to != getNodeNum()) { + bool isAck = ((c && c->error_reason == Routing_Error_NONE)); // consider only ROUTING_APP message without error as ACK + if (isAck && p->to != getNodeNum()) { // do not flood direct message that is ACKed DEBUG_MSG("Receiving an ACK not for me, but don't need to rebroadcast this direct message anymore.\n"); Router::cancelSending(p->to, p->decoded.request_id); // cancel rebroadcast for this DM diff --git a/src/mesh/InterfacesTemplates.cpp b/src/mesh/InterfacesTemplates.cpp index 6707813db..ccef2df23 100644 --- a/src/mesh/InterfacesTemplates.cpp +++ b/src/mesh/InterfacesTemplates.cpp @@ -9,5 +9,5 @@ template class SX126xInterface; template class SX126xInterface; #if !defined(ARCH_PORTDUINO) -template class SX128xInterface; +template class SX128xInterface; #endif \ No newline at end of file diff --git a/src/mesh/MeshModule.cpp b/src/mesh/MeshModule.cpp index 7b204ae49..ca1fb5b50 100644 --- a/src/mesh/MeshModule.cpp +++ b/src/mesh/MeshModule.cpp @@ -109,10 +109,7 @@ void MeshModule::callPlugins(const MeshPacket &mp, RxSource src) /// Also: if a packet comes in on the local PC interface, we don't check for bound channels, because it is TRUSTED and it needs to /// to be able to fetch the initial admin packets without yet knowing any channels. - bool rxChannelOk = !pi.boundChannel || (mp.from == 0) || - !ch || - strlen(ch->settings.name) > 0 || - (strcasecmp(ch->settings.name, pi.boundChannel) == 0); + bool rxChannelOk = !pi.boundChannel || (mp.from == 0) || (strcasecmp(ch->settings.name, pi.boundChannel) == 0); if (!rxChannelOk) { // no one should have already replied! diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index 6b9744565..dcd518191 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -18,7 +18,7 @@ DeviceState versions used to be defined in the .proto file but really only this #define SEGMENT_DEVICESTATE 4 #define SEGMENT_CHANNELS 8 -#define DEVICESTATE_CUR_VER 19 +#define DEVICESTATE_CUR_VER 20 #define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER extern DeviceState devicestate; diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 2f060889a..ea08bf769 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -249,11 +249,15 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_canned_message_tag; fromRadioScratch.moduleConfig.payload_variant.canned_message = moduleConfig.canned_message; break; + case ModuleConfig_audio_tag: + fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_audio_tag; + fromRadioScratch.moduleConfig.payload_variant.audio = moduleConfig.audio; + break; } config_state++; // Advance when we have sent all of our ModuleConfig objects - if (config_state > ModuleConfig_canned_message_tag) { + if (config_state > ModuleConfig_audio_tag) { state = STATE_SEND_COMPLETE_ID; config_state = 0; } diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 07bb01108..97dd66fae 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -361,7 +361,7 @@ void RadioInterface::applyModemConfig() // Set up default configuration // No Sync Words in LORA mode Config_LoRaConfig &loraConfig = config.lora; - if (loraConfig.spread_factor == 0) { + if (loraConfig.use_preset) { switch (loraConfig.modem_preset) { case Config_LoRaConfig_ModemPreset_SHORT_FAST: @@ -416,7 +416,7 @@ void RadioInterface::applyModemConfig() power = loraConfig.tx_power; assert(myRegion); // Should have been found in init - if ((power == 0) || (power > myRegion->powerLimit)) + if ((power == 0) || ((power > myRegion->powerLimit) && !devicestate.owner.is_licensed)) power = myRegion->powerLimit; if (power == 0) @@ -460,7 +460,7 @@ void RadioInterface::limitPower() if (myRegion->powerLimit) maxPower = myRegion->powerLimit; - if (power > maxPower) { + if ((power > maxPower) && !devicestate.owner.is_licensed) { DEBUG_MSG("Lowering transmit power because of regulatory limits\n"); power = maxPower; } diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index 262a10c18..c08220555 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -317,7 +317,13 @@ ErrorCode RadioLibInterface::send(MeshPacket *p) void RadioLibInterface::handleReceiveInterrupt() { uint32_t xmitMsec; - assert(isReceiving); + + // when this is called, we should be in receive mode - if we are not, just jump out instead of bombing. Possible Race Condition? + if (!isReceiving) { + DEBUG_MSG("*** WAS_ASSERT *** handleReceiveInterrupt called when not in receive mode\n"); + return; + } + isReceiving = false; // read the number of actually received bytes diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 815571b9b..e0746bdd9 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -11,7 +11,7 @@ extern "C" { #include "mesh/compression/unishox2.h" } -#if HAS_WIFI +#if HAS_WIFI || HAS_ETHERNET #include "mqtt/MQTT.h" #endif @@ -209,7 +209,7 @@ ErrorCode Router::send(MeshPacket *p) if (p->which_payload_variant == MeshPacket_decoded_tag) { ChannelIndex chIndex = p->channel; // keep as a local because we are about to change it -#if HAS_WIFI +#if HAS_WIFI || HAS_ETHERNET // check if we should send decrypted packets to mqtt // truth table: @@ -240,7 +240,7 @@ ErrorCode Router::send(MeshPacket *p) return encodeResult; // FIXME - this isn't a valid ErrorCode } -#if HAS_WIFI +#if HAS_WIFI || HAS_ETHERNET // the packet is now encrypted. // check if we should send encrypted packets to mqtt if (mqtt && shouldActuallyEncrypt) diff --git a/src/mesh/SX1281Interface.cpp b/src/mesh/SX1280Interface.cpp similarity index 72% rename from src/mesh/SX1281Interface.cpp rename to src/mesh/SX1280Interface.cpp index 50805cfe0..37aad1d40 100644 --- a/src/mesh/SX1281Interface.cpp +++ b/src/mesh/SX1280Interface.cpp @@ -1,10 +1,10 @@ #include "configuration.h" -#include "SX1281Interface.h" +#include "SX1280Interface.h" #include "error.h" #if !defined(ARCH_PORTDUINO) -SX1281Interface::SX1281Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, +SX1280Interface::SX1280Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi) : SX128xInterface(cs, irq, rst, busy, spi) { diff --git a/src/mesh/SX1281Interface.h b/src/mesh/SX1280Interface.h similarity index 52% rename from src/mesh/SX1281Interface.h rename to src/mesh/SX1280Interface.h index 3bd65309a..1c2e24900 100644 --- a/src/mesh/SX1281Interface.h +++ b/src/mesh/SX1280Interface.h @@ -3,15 +3,15 @@ #include "SX128xInterface.h" /** - * Our adapter for SX1281 radios + * Our adapter for SX1280 radios */ #if !defined(ARCH_PORTDUINO) -class SX1281Interface : public SX128xInterface +class SX1280Interface : public SX128xInterface { public: - SX1281Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi); + SX1280Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi); }; #endif \ No newline at end of file diff --git a/src/mesh/SX128xInterface.h b/src/mesh/SX128xInterface.h index d01dfc510..f712b8bc4 100644 --- a/src/mesh/SX128xInterface.h +++ b/src/mesh/SX128xInterface.h @@ -6,7 +6,7 @@ /** * \brief Adapter for SX128x radio family. Implements common logic for child classes. - * \tparam T RadioLib module type for SX128x: SX1281. + * \tparam T RadioLib module type for SX128x: SX1280. */ template class SX128xInterface : public RadioLibInterface diff --git a/src/mesh/eth/ethClient.cpp b/src/mesh/eth/ethClient.cpp new file mode 100644 index 000000000..793a86125 --- /dev/null +++ b/src/mesh/eth/ethClient.cpp @@ -0,0 +1,148 @@ +#include "mesh/eth/ethClient.h" +#include "NodeDB.h" +#include "RTC.h" +#include "concurrency/Periodic.h" +#include +#include +#include "target_specific.h" +#include "mesh/eth/ethServerAPI.h" +#include "mqtt/MQTT.h" + +#ifndef DISABLE_NTP +#include + +// NTP +EthernetUDP ntpUDP; +NTPClient timeClient(ntpUDP, config.network.ntp_server); +uint32_t ntp_renew = 0; +#endif + +bool ethStartupComplete = 0; + +using namespace concurrency; + +static Periodic *ethEvent; + +static int32_t reconnectETH() +{ + if (config.network.eth_enabled) { + Ethernet.maintain(); + if (!ethStartupComplete) { + // Start web server + DEBUG_MSG("... Starting network services\n"); + +#ifndef DISABLE_NTP + DEBUG_MSG("Starting NTP time client\n"); + timeClient.begin(); + timeClient.setUpdateInterval(60 * 60); // Update once an hour +#endif + // initWebServer(); + initApiServer(); + + ethStartupComplete = true; + } + + // FIXME this is kinda yucky, instead we should just have an observable for 'wifireconnected' + if (mqtt && !mqtt->connected()) { + mqtt->reconnect(); + } + } + +#ifndef DISABLE_NTP + if (isEthernetAvailable() && (ntp_renew < millis())) { + + DEBUG_MSG("Updating NTP time from %s\n", config.network.ntp_server); + if (timeClient.update()) { + DEBUG_MSG("NTP Request Success - Setting RTCQualityNTP if needed\n"); + + struct timeval tv; + tv.tv_sec = timeClient.getEpochTime(); + tv.tv_usec = 0; + + perhapsSetRTC(RTCQualityNTP, &tv); + + ntp_renew = millis() + 43200 * 1000; // success, refresh every 12 hours + + } else { + DEBUG_MSG("NTP Update failed\n"); + ntp_renew = millis() + 300 * 1000; // failure, retry every 5 minutes + } + } +#endif + + return 5000; // every 5 seconds +} + +// Startup Ethernet +bool initEthernet() +{ + if (config.network.eth_enabled) { + +#ifdef PIN_ETHERNET_RESET + pinMode(PIN_ETHERNET_RESET, OUTPUT); + digitalWrite(PIN_ETHERNET_RESET, LOW); // Reset Time. + delay(100); + digitalWrite(PIN_ETHERNET_RESET, HIGH); // Reset Time. +#endif + + Ethernet.init( ETH_SPI_PORT, PIN_ETHERNET_SS ); + + uint8_t mac[6]; + + int status = 0; + + // createSSLCert(); + + getMacAddr(mac); // FIXME use the BLE MAC for now... + + if (config.network.eth_mode == Config_NetworkConfig_EthMode_DHCP) { + DEBUG_MSG("starting Ethernet DHCP\n"); + status = Ethernet.begin(mac); + } else if (config.network.eth_mode == Config_NetworkConfig_EthMode_STATIC) { + DEBUG_MSG("starting Ethernet Static\n"); + Ethernet.begin(mac, config.network.ipv4_config.ip, config.network.ipv4_config.dns, config.network.ipv4_config.subnet); + } else { + DEBUG_MSG("Ethernet Disabled\n"); + return false; + } + + if (status == 0) { + if (Ethernet.hardwareStatus() == EthernetNoHardware) { + DEBUG_MSG("Ethernet shield was not found.\n"); + return false; + } else if (Ethernet.linkStatus() == LinkOFF) { + DEBUG_MSG("Ethernet cable is not connected.\n"); + return false; + } else{ + DEBUG_MSG("Unknown Ethernet error.\n"); + return false; + } + } else { + DEBUG_MSG("Local IP %u.%u.%u.%u\n",Ethernet.localIP()[0], Ethernet.localIP()[1], Ethernet.localIP()[2], Ethernet.localIP()[3]); + DEBUG_MSG("Subnet Mask %u.%u.%u.%u\n",Ethernet.subnetMask()[0], Ethernet.subnetMask()[1], Ethernet.subnetMask()[2], Ethernet.subnetMask()[3]); + DEBUG_MSG("Gateway IP %u.%u.%u.%u\n",Ethernet.gatewayIP()[0], Ethernet.gatewayIP()[1], Ethernet.gatewayIP()[2], Ethernet.gatewayIP()[3]); + DEBUG_MSG("DNS Server IP %u.%u.%u.%u\n",Ethernet.dnsServerIP()[0], Ethernet.dnsServerIP()[1], Ethernet.dnsServerIP()[2], Ethernet.dnsServerIP()[3]); + } + + ethEvent = new Periodic("ethConnect", reconnectETH); + + return true; + + } else { + DEBUG_MSG("Not using Ethernet\n"); + return false; + } +} + +bool isEthernetAvailable() { + + if (!config.network.eth_enabled) { + return false; + } else if (Ethernet.hardwareStatus() == EthernetNoHardware) { + return false; + } else if (Ethernet.linkStatus() == LinkOFF) { + return false; + } else { + return true; + } +} diff --git a/src/mesh/eth/ethClient.h b/src/mesh/eth/ethClient.h new file mode 100644 index 000000000..9e1745b9f --- /dev/null +++ b/src/mesh/eth/ethClient.h @@ -0,0 +1,8 @@ +#pragma once + +#include "configuration.h" +#include +#include + +bool initEthernet(); +bool isEthernetAvailable(); diff --git a/src/mesh/eth/ethServerAPI.cpp b/src/mesh/eth/ethServerAPI.cpp new file mode 100644 index 000000000..bb7dd927d --- /dev/null +++ b/src/mesh/eth/ethServerAPI.cpp @@ -0,0 +1,82 @@ +#include "ethServerAPI.h" +#include "configuration.h" +#include + +static ethServerPort *apiPort; + +void initApiServer(int port) +{ + // Start API server on port 4403 + if (!apiPort) { + apiPort = new ethServerPort(port); + DEBUG_MSG("API server listening on TCP port %d\n", port); + apiPort->init(); + } +} + +ethServerAPI::ethServerAPI(EthernetClient &_client) : StreamAPI(&client), client(_client) +{ + DEBUG_MSG("Incoming ethernet connection\n"); +} + +ethServerAPI::~ethServerAPI() +{ + client.stop(); + + // FIXME - delete this if the client dropps the connection! +} + +/// override close to also shutdown the TCP link +void ethServerAPI::close() +{ + client.stop(); // drop tcp connection + StreamAPI::close(); +} + +/// Check the current underlying physical link to see if the client is currently connected +bool ethServerAPI::checkIsConnected() +{ + return client.connected(); +} + +int32_t ethServerAPI::runOnce() +{ + if (client.connected()) { + return StreamAPI::runOnce(); + } else { + DEBUG_MSG("Client dropped connection, suspending API service\n"); + enabled = false; // we no longer need to run + return 0; + } +} + +/// If an api server is running, we try to spit out debug 'serial' characters there +void ethServerPort::debugOut(char c) +{ + if (apiPort && apiPort->openAPI) + apiPort->openAPI->debugOut(c); +} + + +ethServerPort::ethServerPort(int port) : EthernetServer(port), concurrency::OSThread("ApiServer") {} + +void ethServerPort::init() +{ + begin(); +} + +int32_t ethServerPort::runOnce() +{ + auto client = available(); + if (client) { + // Close any previous connection (see FIXME in header file) + if (openAPI) { + DEBUG_MSG("Force closing previous TCP connection\n"); + delete openAPI; + } + + openAPI = new ethServerAPI(client); + } + + return 100; // only check occasionally for incoming connections +} diff --git a/src/mesh/eth/ethServerAPI.h b/src/mesh/eth/ethServerAPI.h new file mode 100644 index 000000000..c92ab2f17 --- /dev/null +++ b/src/mesh/eth/ethServerAPI.h @@ -0,0 +1,58 @@ +#pragma once + +#include "StreamAPI.h" +#include + +/** + * Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs + * (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs). + */ +class ethServerAPI : public StreamAPI +{ + private: + EthernetClient client; + + public: + explicit ethServerAPI(EthernetClient &_client); + + virtual ~ethServerAPI(); + + /// override close to also shutdown the TCP link + virtual void close(); + + protected: + /// We override this method to prevent publishing EVENT_SERIAL_CONNECTED/DISCONNECTED for wifi links (we want the board to + /// stay in the POWERED state to prevent disabling wifi) + virtual void onConnectionChanged(bool connected) override {} + + virtual int32_t runOnce() override; // Check for dropped client connections + + /// Check the current underlying physical link to see if the client is currently connected + virtual bool checkIsConnected() override; +}; + +/** + * Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed + */ +class ethServerPort : public EthernetServer, private concurrency::OSThread +{ + /** The currently open port + * + * FIXME: We currently only allow one open TCP connection at a time, because we depend on the loop() call in this class to + * delegate to the worker. Once coroutines are implemented we can relax this restriction. + */ + ethServerAPI *openAPI = NULL; + + public: + explicit ethServerPort(int port); + + void init(); + + /// If an api server is running, we try to spit out debug 'serial' characters there + static void debugOut(char c); + + protected: + int32_t runOnce() override; +}; + +void initApiServer(int port=4403); diff --git a/src/mesh/generated/admin.pb.h b/src/mesh/generated/admin.pb.h index 9b93bfd44..b5dc769ca 100644 --- a/src/mesh/generated/admin.pb.h +++ b/src/mesh/generated/admin.pb.h @@ -32,7 +32,8 @@ typedef enum _AdminMessage_ModuleConfigType { AdminMessage_ModuleConfigType_STOREFORWARD_CONFIG = 3, AdminMessage_ModuleConfigType_RANGETEST_CONFIG = 4, AdminMessage_ModuleConfigType_TELEMETRY_CONFIG = 5, - AdminMessage_ModuleConfigType_CANNEDMSG_CONFIG = 6 + AdminMessage_ModuleConfigType_CANNEDMSG_CONFIG = 6, + AdminMessage_ModuleConfigType_AUDIO_CONFIG = 7 } AdminMessage_ModuleConfigType; /* Struct definitions */ @@ -116,8 +117,8 @@ typedef struct _AdminMessage { #define _AdminMessage_ConfigType_ARRAYSIZE ((AdminMessage_ConfigType)(AdminMessage_ConfigType_BLUETOOTH_CONFIG+1)) #define _AdminMessage_ModuleConfigType_MIN AdminMessage_ModuleConfigType_MQTT_CONFIG -#define _AdminMessage_ModuleConfigType_MAX AdminMessage_ModuleConfigType_CANNEDMSG_CONFIG -#define _AdminMessage_ModuleConfigType_ARRAYSIZE ((AdminMessage_ModuleConfigType)(AdminMessage_ModuleConfigType_CANNEDMSG_CONFIG+1)) +#define _AdminMessage_ModuleConfigType_MAX AdminMessage_ModuleConfigType_AUDIO_CONFIG +#define _AdminMessage_ModuleConfigType_ARRAYSIZE ((AdminMessage_ModuleConfigType)(AdminMessage_ModuleConfigType_AUDIO_CONFIG+1)) #ifdef __cplusplus diff --git a/src/mesh/generated/config.pb.c b/src/mesh/generated/config.pb.c index 7d2efe91d..c5bc69552 100644 --- a/src/mesh/generated/config.pb.c +++ b/src/mesh/generated/config.pb.c @@ -21,6 +21,9 @@ PB_BIND(Config_PowerConfig, Config_PowerConfig, AUTO) PB_BIND(Config_NetworkConfig, Config_NetworkConfig, AUTO) +PB_BIND(Config_NetworkConfig_IpV4Config, Config_NetworkConfig_IpV4Config, AUTO) + + PB_BIND(Config_DisplayConfig, Config_DisplayConfig, AUTO) @@ -39,3 +42,4 @@ PB_BIND(Config_BluetoothConfig, Config_BluetoothConfig, AUTO) + diff --git a/src/mesh/generated/config.pb.h b/src/mesh/generated/config.pb.h index 940771580..9748383cb 100644 --- a/src/mesh/generated/config.pb.h +++ b/src/mesh/generated/config.pb.h @@ -31,11 +31,10 @@ typedef enum _Config_PositionConfig_PositionFlags { Config_PositionConfig_PositionFlags_SPEED = 512 } Config_PositionConfig_PositionFlags; -typedef enum _Config_NetworkConfig_WiFiMode { - Config_NetworkConfig_WiFiMode_CLIENT = 0, - Config_NetworkConfig_WiFiMode_ACCESS_POINT = 1, - Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN = 2 -} Config_NetworkConfig_WiFiMode; +typedef enum _Config_NetworkConfig_EthMode { + Config_NetworkConfig_EthMode_DHCP = 0, + Config_NetworkConfig_EthMode_STATIC = 1 +} Config_NetworkConfig_EthMode; typedef enum _Config_DisplayConfig_GpsCoordinateFormat { Config_DisplayConfig_GpsCoordinateFormat_DEC = 0, @@ -51,6 +50,12 @@ typedef enum _Config_DisplayConfig_DisplayUnits { Config_DisplayConfig_DisplayUnits_IMPERIAL = 1 } Config_DisplayConfig_DisplayUnits; +typedef enum _Config_DisplayConfig_OledType { + Config_DisplayConfig_OledType_OLED_AUTO = 0, + Config_DisplayConfig_OledType_OLED_SSD1306 = 1, + Config_DisplayConfig_OledType_OLED_SH1106 = 2 +} Config_DisplayConfig_OledType; + typedef enum _Config_LoRaConfig_RegionCode { Config_LoRaConfig_RegionCode_UNSET = 0, Config_LoRaConfig_RegionCode_US = 1, @@ -104,6 +109,7 @@ typedef struct _Config_DisplayConfig { bool compass_north_top; bool flip_screen; Config_DisplayConfig_DisplayUnits units; + Config_DisplayConfig_OledType oled; } Config_DisplayConfig; typedef struct _Config_LoRaConfig { @@ -122,13 +128,12 @@ typedef struct _Config_LoRaConfig { uint32_t ignore_incoming[3]; } Config_LoRaConfig; -typedef struct _Config_NetworkConfig { - bool wifi_enabled; - Config_NetworkConfig_WiFiMode wifi_mode; - char wifi_ssid[33]; - char wifi_psk[64]; - char ntp_server[33]; -} Config_NetworkConfig; +typedef struct _Config_NetworkConfig_IpV4Config { + uint32_t ip; + uint32_t gateway; + uint32_t subnet; + uint32_t dns; +} Config_NetworkConfig_IpV4Config; typedef struct _Config_PositionConfig { uint32_t position_broadcast_secs; @@ -151,6 +156,17 @@ typedef struct _Config_PowerConfig { uint32_t min_wake_secs; } Config_PowerConfig; +typedef struct _Config_NetworkConfig { + bool wifi_enabled; + char wifi_ssid[33]; + char wifi_psk[64]; + char ntp_server[33]; + bool eth_enabled; + Config_NetworkConfig_EthMode eth_mode; + bool has_ipv4_config; + Config_NetworkConfig_IpV4Config ipv4_config; +} Config_NetworkConfig; + typedef struct _Config { pb_size_t which_payload_variant; union { @@ -174,9 +190,9 @@ typedef struct _Config { #define _Config_PositionConfig_PositionFlags_MAX Config_PositionConfig_PositionFlags_SPEED #define _Config_PositionConfig_PositionFlags_ARRAYSIZE ((Config_PositionConfig_PositionFlags)(Config_PositionConfig_PositionFlags_SPEED+1)) -#define _Config_NetworkConfig_WiFiMode_MIN Config_NetworkConfig_WiFiMode_CLIENT -#define _Config_NetworkConfig_WiFiMode_MAX Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN -#define _Config_NetworkConfig_WiFiMode_ARRAYSIZE ((Config_NetworkConfig_WiFiMode)(Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN+1)) +#define _Config_NetworkConfig_EthMode_MIN Config_NetworkConfig_EthMode_DHCP +#define _Config_NetworkConfig_EthMode_MAX Config_NetworkConfig_EthMode_STATIC +#define _Config_NetworkConfig_EthMode_ARRAYSIZE ((Config_NetworkConfig_EthMode)(Config_NetworkConfig_EthMode_STATIC+1)) #define _Config_DisplayConfig_GpsCoordinateFormat_MIN Config_DisplayConfig_GpsCoordinateFormat_DEC #define _Config_DisplayConfig_GpsCoordinateFormat_MAX Config_DisplayConfig_GpsCoordinateFormat_OSGR @@ -186,6 +202,10 @@ typedef struct _Config { #define _Config_DisplayConfig_DisplayUnits_MAX Config_DisplayConfig_DisplayUnits_IMPERIAL #define _Config_DisplayConfig_DisplayUnits_ARRAYSIZE ((Config_DisplayConfig_DisplayUnits)(Config_DisplayConfig_DisplayUnits_IMPERIAL+1)) +#define _Config_DisplayConfig_OledType_MIN Config_DisplayConfig_OledType_OLED_AUTO +#define _Config_DisplayConfig_OledType_MAX Config_DisplayConfig_OledType_OLED_SH1106 +#define _Config_DisplayConfig_OledType_ARRAYSIZE ((Config_DisplayConfig_OledType)(Config_DisplayConfig_OledType_OLED_SH1106+1)) + #define _Config_LoRaConfig_RegionCode_MIN Config_LoRaConfig_RegionCode_UNSET #define _Config_LoRaConfig_RegionCode_MAX Config_LoRaConfig_RegionCode_LORA_24 #define _Config_LoRaConfig_RegionCode_ARRAYSIZE ((Config_LoRaConfig_RegionCode)(Config_LoRaConfig_RegionCode_LORA_24+1)) @@ -208,16 +228,18 @@ extern "C" { #define Config_DeviceConfig_init_default {_Config_DeviceConfig_Role_MIN, 0, 0} #define Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0} #define Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0} -#define Config_NetworkConfig_init_default {0, _Config_NetworkConfig_WiFiMode_MIN, "", "", ""} -#define Config_DisplayConfig_init_default {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _Config_DisplayConfig_DisplayUnits_MIN} +#define Config_NetworkConfig_init_default {0, "", "", "", 0, _Config_NetworkConfig_EthMode_MIN, false, Config_NetworkConfig_IpV4Config_init_default} +#define Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0} +#define Config_DisplayConfig_init_default {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _Config_DisplayConfig_DisplayUnits_MIN, _Config_DisplayConfig_OledType_MIN} #define Config_LoRaConfig_init_default {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, {0, 0, 0}} #define Config_BluetoothConfig_init_default {0, _Config_BluetoothConfig_PairingMode_MIN, 0} #define Config_init_zero {0, {Config_DeviceConfig_init_zero}} #define Config_DeviceConfig_init_zero {_Config_DeviceConfig_Role_MIN, 0, 0} #define Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0} #define Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0} -#define Config_NetworkConfig_init_zero {0, _Config_NetworkConfig_WiFiMode_MIN, "", "", ""} -#define Config_DisplayConfig_init_zero {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _Config_DisplayConfig_DisplayUnits_MIN} +#define Config_NetworkConfig_init_zero {0, "", "", "", 0, _Config_NetworkConfig_EthMode_MIN, false, Config_NetworkConfig_IpV4Config_init_zero} +#define Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0} +#define Config_DisplayConfig_init_zero {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _Config_DisplayConfig_DisplayUnits_MIN, _Config_DisplayConfig_OledType_MIN} #define Config_LoRaConfig_init_zero {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, {0, 0, 0}} #define Config_BluetoothConfig_init_zero {0, _Config_BluetoothConfig_PairingMode_MIN, 0} @@ -234,6 +256,7 @@ extern "C" { #define Config_DisplayConfig_compass_north_top_tag 4 #define Config_DisplayConfig_flip_screen_tag 5 #define Config_DisplayConfig_units_tag 6 +#define Config_DisplayConfig_oled_tag 7 #define Config_LoRaConfig_use_preset_tag 1 #define Config_LoRaConfig_modem_preset_tag 2 #define Config_LoRaConfig_bandwidth_tag 3 @@ -246,11 +269,10 @@ extern "C" { #define Config_LoRaConfig_tx_power_tag 10 #define Config_LoRaConfig_channel_num_tag 11 #define Config_LoRaConfig_ignore_incoming_tag 103 -#define Config_NetworkConfig_wifi_enabled_tag 1 -#define Config_NetworkConfig_wifi_mode_tag 2 -#define Config_NetworkConfig_wifi_ssid_tag 3 -#define Config_NetworkConfig_wifi_psk_tag 4 -#define Config_NetworkConfig_ntp_server_tag 5 +#define Config_NetworkConfig_IpV4Config_ip_tag 1 +#define Config_NetworkConfig_IpV4Config_gateway_tag 2 +#define Config_NetworkConfig_IpV4Config_subnet_tag 3 +#define Config_NetworkConfig_IpV4Config_dns_tag 4 #define Config_PositionConfig_position_broadcast_secs_tag 1 #define Config_PositionConfig_position_broadcast_smart_enabled_tag 2 #define Config_PositionConfig_fixed_position_tag 3 @@ -266,6 +288,13 @@ extern "C" { #define Config_PowerConfig_sds_secs_tag 6 #define Config_PowerConfig_ls_secs_tag 7 #define Config_PowerConfig_min_wake_secs_tag 8 +#define Config_NetworkConfig_wifi_enabled_tag 1 +#define Config_NetworkConfig_wifi_ssid_tag 3 +#define Config_NetworkConfig_wifi_psk_tag 4 +#define Config_NetworkConfig_ntp_server_tag 5 +#define Config_NetworkConfig_eth_enabled_tag 6 +#define Config_NetworkConfig_eth_mode_tag 7 +#define Config_NetworkConfig_ipv4_config_tag 8 #define Config_device_tag 1 #define Config_position_tag 2 #define Config_power_tag 3 @@ -325,12 +354,23 @@ X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 8) #define Config_NetworkConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, BOOL, wifi_enabled, 1) \ -X(a, STATIC, SINGULAR, UENUM, wifi_mode, 2) \ X(a, STATIC, SINGULAR, STRING, wifi_ssid, 3) \ X(a, STATIC, SINGULAR, STRING, wifi_psk, 4) \ -X(a, STATIC, SINGULAR, STRING, ntp_server, 5) +X(a, STATIC, SINGULAR, STRING, ntp_server, 5) \ +X(a, STATIC, SINGULAR, BOOL, eth_enabled, 6) \ +X(a, STATIC, SINGULAR, UENUM, eth_mode, 7) \ +X(a, STATIC, OPTIONAL, MESSAGE, ipv4_config, 8) #define Config_NetworkConfig_CALLBACK NULL #define Config_NetworkConfig_DEFAULT NULL +#define Config_NetworkConfig_ipv4_config_MSGTYPE Config_NetworkConfig_IpV4Config + +#define Config_NetworkConfig_IpV4Config_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, FIXED32, ip, 1) \ +X(a, STATIC, SINGULAR, FIXED32, gateway, 2) \ +X(a, STATIC, SINGULAR, FIXED32, subnet, 3) \ +X(a, STATIC, SINGULAR, FIXED32, dns, 4) +#define Config_NetworkConfig_IpV4Config_CALLBACK NULL +#define Config_NetworkConfig_IpV4Config_DEFAULT NULL #define Config_DisplayConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, screen_on_secs, 1) \ @@ -338,7 +378,8 @@ X(a, STATIC, SINGULAR, UENUM, gps_format, 2) \ X(a, STATIC, SINGULAR, UINT32, auto_screen_carousel_secs, 3) \ X(a, STATIC, SINGULAR, BOOL, compass_north_top, 4) \ X(a, STATIC, SINGULAR, BOOL, flip_screen, 5) \ -X(a, STATIC, SINGULAR, UENUM, units, 6) +X(a, STATIC, SINGULAR, UENUM, units, 6) \ +X(a, STATIC, SINGULAR, UENUM, oled, 7) #define Config_DisplayConfig_CALLBACK NULL #define Config_DisplayConfig_DEFAULT NULL @@ -370,6 +411,7 @@ extern const pb_msgdesc_t Config_DeviceConfig_msg; extern const pb_msgdesc_t Config_PositionConfig_msg; extern const pb_msgdesc_t Config_PowerConfig_msg; extern const pb_msgdesc_t Config_NetworkConfig_msg; +extern const pb_msgdesc_t Config_NetworkConfig_IpV4Config_msg; extern const pb_msgdesc_t Config_DisplayConfig_msg; extern const pb_msgdesc_t Config_LoRaConfig_msg; extern const pb_msgdesc_t Config_BluetoothConfig_msg; @@ -380,6 +422,7 @@ extern const pb_msgdesc_t Config_BluetoothConfig_msg; #define Config_PositionConfig_fields &Config_PositionConfig_msg #define Config_PowerConfig_fields &Config_PowerConfig_msg #define Config_NetworkConfig_fields &Config_NetworkConfig_msg +#define Config_NetworkConfig_IpV4Config_fields &Config_NetworkConfig_IpV4Config_msg #define Config_DisplayConfig_fields &Config_DisplayConfig_msg #define Config_LoRaConfig_fields &Config_LoRaConfig_msg #define Config_BluetoothConfig_fields &Config_BluetoothConfig_msg @@ -387,12 +430,13 @@ extern const pb_msgdesc_t Config_BluetoothConfig_msg; /* Maximum encoded size of messages (where known) */ #define Config_BluetoothConfig_size 10 #define Config_DeviceConfig_size 6 -#define Config_DisplayConfig_size 20 +#define Config_DisplayConfig_size 22 #define Config_LoRaConfig_size 68 -#define Config_NetworkConfig_size 137 +#define Config_NetworkConfig_IpV4Config_size 20 +#define Config_NetworkConfig_size 161 #define Config_PositionConfig_size 30 #define Config_PowerConfig_size 43 -#define Config_size 140 +#define Config_size 164 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/device_metadata.pb.h b/src/mesh/generated/device_metadata.pb.h index 7bd32979e..1f4c81c5b 100644 --- a/src/mesh/generated/device_metadata.pb.h +++ b/src/mesh/generated/device_metadata.pb.h @@ -16,6 +16,14 @@ typedef struct _DeviceMetadata { char firmware_version[18]; /* Device state version */ uint32_t device_state_version; + /* Indicates whether the device can shutdown CPU natively or via power management chip */ + bool canShutdown; + /* Indicates that the device has native wifi capability */ + bool hasWifi; + /* Indicates that the device has native bluetooth capability */ + bool hasBluetooth; + /* Indicates that the device has an ethernet peripheral */ + bool hasEthernet; } DeviceMetadata; @@ -24,17 +32,25 @@ extern "C" { #endif /* Initializer values for message structs */ -#define DeviceMetadata_init_default {"", 0} -#define DeviceMetadata_init_zero {"", 0} +#define DeviceMetadata_init_default {"", 0, 0, 0, 0, 0} +#define DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0} /* Field tags (for use in manual encoding/decoding) */ #define DeviceMetadata_firmware_version_tag 1 #define DeviceMetadata_device_state_version_tag 2 +#define DeviceMetadata_canShutdown_tag 3 +#define DeviceMetadata_hasWifi_tag 4 +#define DeviceMetadata_hasBluetooth_tag 5 +#define DeviceMetadata_hasEthernet_tag 6 /* Struct field encoding specification for nanopb */ #define DeviceMetadata_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, firmware_version, 1) \ -X(a, STATIC, SINGULAR, UINT32, device_state_version, 2) +X(a, STATIC, SINGULAR, UINT32, device_state_version, 2) \ +X(a, STATIC, SINGULAR, BOOL, canShutdown, 3) \ +X(a, STATIC, SINGULAR, BOOL, hasWifi, 4) \ +X(a, STATIC, SINGULAR, BOOL, hasBluetooth, 5) \ +X(a, STATIC, SINGULAR, BOOL, hasEthernet, 6) #define DeviceMetadata_CALLBACK NULL #define DeviceMetadata_DEFAULT NULL @@ -44,7 +60,7 @@ extern const pb_msgdesc_t DeviceMetadata_msg; #define DeviceMetadata_fields &DeviceMetadata_msg /* Maximum encoded size of messages (where known) */ -#define DeviceMetadata_size 25 +#define DeviceMetadata_size 33 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/localonly.pb.h b/src/mesh/generated/localonly.pb.h index d4c5fb012..783c523c7 100644 --- a/src/mesh/generated/localonly.pb.h +++ b/src/mesh/generated/localonly.pb.h @@ -66,6 +66,9 @@ typedef struct _LocalModuleConfig { incompatible changes This integer is set at build time and is private to NodeDB.cpp in the device code. */ uint32_t version; + /* The part of the config that is specific to the Audio module */ + bool has_audio; + ModuleConfig_AudioConfig audio; } LocalModuleConfig; @@ -75,9 +78,9 @@ extern "C" { /* Initializer values for message structs */ #define LocalConfig_init_default {false, Config_DeviceConfig_init_default, false, Config_PositionConfig_init_default, false, Config_PowerConfig_init_default, false, Config_NetworkConfig_init_default, false, Config_DisplayConfig_init_default, false, Config_LoRaConfig_init_default, false, Config_BluetoothConfig_init_default, 0} -#define LocalModuleConfig_init_default {false, ModuleConfig_MQTTConfig_init_default, false, ModuleConfig_SerialConfig_init_default, false, ModuleConfig_ExternalNotificationConfig_init_default, false, ModuleConfig_StoreForwardConfig_init_default, false, ModuleConfig_RangeTestConfig_init_default, false, ModuleConfig_TelemetryConfig_init_default, false, ModuleConfig_CannedMessageConfig_init_default, 0} +#define LocalModuleConfig_init_default {false, ModuleConfig_MQTTConfig_init_default, false, ModuleConfig_SerialConfig_init_default, false, ModuleConfig_ExternalNotificationConfig_init_default, false, ModuleConfig_StoreForwardConfig_init_default, false, ModuleConfig_RangeTestConfig_init_default, false, ModuleConfig_TelemetryConfig_init_default, false, ModuleConfig_CannedMessageConfig_init_default, 0, false, ModuleConfig_AudioConfig_init_default} #define LocalConfig_init_zero {false, Config_DeviceConfig_init_zero, false, Config_PositionConfig_init_zero, false, Config_PowerConfig_init_zero, false, Config_NetworkConfig_init_zero, false, Config_DisplayConfig_init_zero, false, Config_LoRaConfig_init_zero, false, Config_BluetoothConfig_init_zero, 0} -#define LocalModuleConfig_init_zero {false, ModuleConfig_MQTTConfig_init_zero, false, ModuleConfig_SerialConfig_init_zero, false, ModuleConfig_ExternalNotificationConfig_init_zero, false, ModuleConfig_StoreForwardConfig_init_zero, false, ModuleConfig_RangeTestConfig_init_zero, false, ModuleConfig_TelemetryConfig_init_zero, false, ModuleConfig_CannedMessageConfig_init_zero, 0} +#define LocalModuleConfig_init_zero {false, ModuleConfig_MQTTConfig_init_zero, false, ModuleConfig_SerialConfig_init_zero, false, ModuleConfig_ExternalNotificationConfig_init_zero, false, ModuleConfig_StoreForwardConfig_init_zero, false, ModuleConfig_RangeTestConfig_init_zero, false, ModuleConfig_TelemetryConfig_init_zero, false, ModuleConfig_CannedMessageConfig_init_zero, 0, false, ModuleConfig_AudioConfig_init_zero} /* Field tags (for use in manual encoding/decoding) */ #define LocalConfig_device_tag 1 @@ -96,6 +99,7 @@ extern "C" { #define LocalModuleConfig_telemetry_tag 6 #define LocalModuleConfig_canned_message_tag 7 #define LocalModuleConfig_version_tag 8 +#define LocalModuleConfig_audio_tag 9 /* Struct field encoding specification for nanopb */ #define LocalConfig_FIELDLIST(X, a) \ @@ -125,7 +129,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, store_forward, 4) \ X(a, STATIC, OPTIONAL, MESSAGE, range_test, 5) \ X(a, STATIC, OPTIONAL, MESSAGE, telemetry, 6) \ X(a, STATIC, OPTIONAL, MESSAGE, canned_message, 7) \ -X(a, STATIC, SINGULAR, UINT32, version, 8) +X(a, STATIC, SINGULAR, UINT32, version, 8) \ +X(a, STATIC, OPTIONAL, MESSAGE, audio, 9) #define LocalModuleConfig_CALLBACK NULL #define LocalModuleConfig_DEFAULT NULL #define LocalModuleConfig_mqtt_MSGTYPE ModuleConfig_MQTTConfig @@ -135,6 +140,7 @@ X(a, STATIC, SINGULAR, UINT32, version, 8) #define LocalModuleConfig_range_test_MSGTYPE ModuleConfig_RangeTestConfig #define LocalModuleConfig_telemetry_MSGTYPE ModuleConfig_TelemetryConfig #define LocalModuleConfig_canned_message_MSGTYPE ModuleConfig_CannedMessageConfig +#define LocalModuleConfig_audio_MSGTYPE ModuleConfig_AudioConfig extern const pb_msgdesc_t LocalConfig_msg; extern const pb_msgdesc_t LocalModuleConfig_msg; @@ -144,8 +150,8 @@ extern const pb_msgdesc_t LocalModuleConfig_msg; #define LocalModuleConfig_fields &LocalModuleConfig_msg /* Maximum encoded size of messages (where known) */ -#define LocalConfig_size 335 -#define LocalModuleConfig_size 270 +#define LocalConfig_size 361 +#define LocalModuleConfig_size 294 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/mesh.pb.c b/src/mesh/generated/mesh.pb.c index 2d46c960c..f98316a5d 100644 --- a/src/mesh/generated/mesh.pb.c +++ b/src/mesh/generated/mesh.pb.c @@ -42,9 +42,6 @@ PB_BIND(FromRadio, FromRadio, 2) PB_BIND(ToRadio, ToRadio, 2) -PB_BIND(ToRadio_PeerInfo, ToRadio_PeerInfo, AUTO) - - PB_BIND(Compressed, Compressed, AUTO) diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index ee72ff504..8e73a0972 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -52,6 +52,8 @@ typedef enum _HardwareModel { HardwareModel_RAK11200 = 13, /* B&Q Consulting Nano Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:nano */ HardwareModel_NANO_G1 = 14, + /* TODO: REPLACE */ + HardwareModel_TLORA_V2_1_1P8 = 15, /* B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station */ HardwareModel_STATION_G1 = 25, /* Less common/prototype boards listed here (needs one more byte over the air) */ @@ -243,8 +245,11 @@ typedef enum _LogRecord_Level { /* Struct definitions */ typedef PB_BYTES_ARRAY_T(237) Compressed_data_t; +/* Compressed message payload */ typedef struct _Compressed { + /* PortNum to determine the how to handle the compressed payload. */ PortNum portnum; + /* Compressed data. */ Compressed_data_t data; } Compressed; @@ -352,7 +357,7 @@ typedef struct _MyNodeInfo { /* a gps position */ typedef struct _Position { - /* The new preferred location encoding, divide by 1e-7 to get degrees + /* The new preferred location encoding, multiply by 1e-7 to get degrees in floating point */ int32_t latitude_i; /* TODO: REPLACE */ @@ -425,14 +430,6 @@ typedef struct _RouteDiscovery { uint32_t route[8]; } RouteDiscovery; -/* Compressed message payload */ -typedef struct _ToRadio_PeerInfo { - /* PortNum to determine the how to handle the compressed payload. */ - uint32_t app_version; - /* Compressed data. */ - bool mqtt_gateway; -} ToRadio_PeerInfo; - /* Broadcast when a newly powered mesh node wants to find a node num it can use Sent from the phone over bluetooth to set the user id for the owner of this node. Also sent from nodes to each other when a new node signs on (so all clients can have this info) @@ -504,7 +501,7 @@ typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t; typedef struct _MeshPacket { /* The sending node number. Note: Our crypto implementation uses this field as well. - See [crypto](/docs/developers/firmware/encryption) for details. + See [crypto](/docs/overview/encryption) for details. FIXME - really should be fixed32 instead, this encoding only hurts the ble link though. */ uint32_t from; /* The (immediatSee Priority description for more details.y should be fixed32 instead, this encoding only @@ -532,7 +529,7 @@ typedef struct _MeshPacket { needs to be unique for a few minutes (long enough to last for the length of any ACK or the completion of a mesh broadcast flood). Note: Our crypto implementation uses this id as well. - See [crypto](/docs/developers/firmware/encryption) for details. + See [crypto](/docs/overview/encryption) for details. FIXME - really should be fixed32 instead, this encoding only hurts the ble link though. */ uint32_t id; @@ -665,9 +662,6 @@ typedef struct _ToRadio { union { /* Send this packet on the mesh */ MeshPacket packet; - /* Information about the peer, sent after the phone sneds want_config_id. - Old clients do not send this, which is fine. */ - ToRadio_PeerInfo peer_info; /* Phone wants radio to send full node db to the phone, This is typically the first packet sent to the radio when the phone gets a bluetooth connection. The radio will respond by sending back a @@ -740,7 +734,6 @@ extern "C" { #define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN} #define FromRadio_init_default {0, 0, {MeshPacket_init_default}} #define ToRadio_init_default {0, {MeshPacket_init_default}} -#define ToRadio_PeerInfo_init_default {0, 0} #define Compressed_init_default {_PortNum_MIN, {0, {0}}} #define Position_init_zero {0, 0, 0, 0, _Position_LocSource_MIN, _Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define User_init_zero {"", "", "", {0}, _HardwareModel_MIN, 0} @@ -754,7 +747,6 @@ extern "C" { #define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN} #define FromRadio_init_zero {0, 0, {MeshPacket_init_zero}} #define ToRadio_init_zero {0, {MeshPacket_init_zero}} -#define ToRadio_PeerInfo_init_zero {0, 0} #define Compressed_init_zero {_PortNum_MIN, {0, {0}}} /* Field tags (for use in manual encoding/decoding) */ @@ -811,8 +803,6 @@ extern "C" { #define Position_next_update_tag 21 #define Position_seq_number_tag 22 #define RouteDiscovery_route_tag 1 -#define ToRadio_PeerInfo_app_version_tag 1 -#define ToRadio_PeerInfo_mqtt_gateway_tag 2 #define User_id_tag 1 #define User_long_name_tag 2 #define User_short_name_tag 3 @@ -859,7 +849,6 @@ extern "C" { #define FromRadio_moduleConfig_tag 9 #define FromRadio_channel_tag 10 #define ToRadio_packet_tag 1 -#define ToRadio_peer_info_tag 2 #define ToRadio_want_config_id_tag 3 #define ToRadio_disconnect_tag 4 @@ -1019,19 +1008,11 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,channel,channel), 10) #define ToRadio_FIELDLIST(X, a) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,packet,packet), 1) \ -X(a, STATIC, ONEOF, MESSAGE, (payload_variant,peer_info,peer_info), 2) \ X(a, STATIC, ONEOF, UINT32, (payload_variant,want_config_id,want_config_id), 3) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,disconnect,disconnect), 4) #define ToRadio_CALLBACK NULL #define ToRadio_DEFAULT NULL #define ToRadio_payload_variant_packet_MSGTYPE MeshPacket -#define ToRadio_payload_variant_peer_info_MSGTYPE ToRadio_PeerInfo - -#define ToRadio_PeerInfo_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, app_version, 1) \ -X(a, STATIC, SINGULAR, BOOL, mqtt_gateway, 2) -#define ToRadio_PeerInfo_CALLBACK NULL -#define ToRadio_PeerInfo_DEFAULT NULL #define Compressed_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, portnum, 1) \ @@ -1051,7 +1032,6 @@ extern const pb_msgdesc_t MyNodeInfo_msg; extern const pb_msgdesc_t LogRecord_msg; extern const pb_msgdesc_t FromRadio_msg; extern const pb_msgdesc_t ToRadio_msg; -extern const pb_msgdesc_t ToRadio_PeerInfo_msg; extern const pb_msgdesc_t Compressed_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ @@ -1067,7 +1047,6 @@ extern const pb_msgdesc_t Compressed_msg; #define LogRecord_fields &LogRecord_msg #define FromRadio_fields &FromRadio_msg #define ToRadio_fields &ToRadio_msg -#define ToRadio_PeerInfo_fields &ToRadio_PeerInfo_msg #define Compressed_fields &Compressed_msg /* Maximum encoded size of messages (where known) */ @@ -1081,7 +1060,6 @@ extern const pb_msgdesc_t Compressed_msg; #define Position_size 137 #define RouteDiscovery_size 40 #define Routing_size 42 -#define ToRadio_PeerInfo_size 8 #define ToRadio_size 324 #define User_size 77 #define Waypoint_size 156 diff --git a/src/mesh/generated/module_config.pb.c b/src/mesh/generated/module_config.pb.c index a3e4ddfbe..381ce6351 100644 --- a/src/mesh/generated/module_config.pb.c +++ b/src/mesh/generated/module_config.pb.c @@ -12,6 +12,9 @@ PB_BIND(ModuleConfig, ModuleConfig, AUTO) PB_BIND(ModuleConfig_MQTTConfig, ModuleConfig_MQTTConfig, AUTO) +PB_BIND(ModuleConfig_AudioConfig, ModuleConfig_AudioConfig, AUTO) + + PB_BIND(ModuleConfig_SerialConfig, ModuleConfig_SerialConfig, AUTO) @@ -34,3 +37,4 @@ PB_BIND(ModuleConfig_CannedMessageConfig, ModuleConfig_CannedMessageConfig, AUTO + diff --git a/src/mesh/generated/module_config.pb.h b/src/mesh/generated/module_config.pb.h index b0f14eea2..af4d4dce9 100644 --- a/src/mesh/generated/module_config.pb.h +++ b/src/mesh/generated/module_config.pb.h @@ -10,6 +10,18 @@ #endif /* Enum definitions */ +typedef enum _ModuleConfig_AudioConfig_Audio_Baud { + ModuleConfig_AudioConfig_Audio_Baud_CODEC2_DEFAULT = 0, + ModuleConfig_AudioConfig_Audio_Baud_CODEC2_3200 = 1, + ModuleConfig_AudioConfig_Audio_Baud_CODEC2_2400 = 2, + ModuleConfig_AudioConfig_Audio_Baud_CODEC2_1600 = 3, + ModuleConfig_AudioConfig_Audio_Baud_CODEC2_1400 = 4, + ModuleConfig_AudioConfig_Audio_Baud_CODEC2_1300 = 5, + ModuleConfig_AudioConfig_Audio_Baud_CODEC2_1200 = 6, + ModuleConfig_AudioConfig_Audio_Baud_CODEC2_700 = 7, + ModuleConfig_AudioConfig_Audio_Baud_CODEC2_700B = 8 +} ModuleConfig_AudioConfig_Audio_Baud; + typedef enum _ModuleConfig_SerialConfig_Serial_Baud { ModuleConfig_SerialConfig_Serial_Baud_BAUD_DEFAULT = 0, ModuleConfig_SerialConfig_Serial_Baud_BAUD_110 = 1, @@ -49,6 +61,14 @@ typedef enum _ModuleConfig_CannedMessageConfig_InputEventChar { } ModuleConfig_CannedMessageConfig_InputEventChar; /* Struct definitions */ +typedef struct _ModuleConfig_AudioConfig { + bool codec2_enabled; + uint32_t mic_chan; + uint32_t amp_pin; + uint32_t ptt_pin; + ModuleConfig_AudioConfig_Audio_Baud bitrate; +} ModuleConfig_AudioConfig; + typedef struct _ModuleConfig_CannedMessageConfig { bool rotary1_enabled; uint32_t inputbroker_pin_a; @@ -131,11 +151,17 @@ typedef struct _ModuleConfig { ModuleConfig_TelemetryConfig telemetry; /* TODO: REPLACE */ ModuleConfig_CannedMessageConfig canned_message; + /* TODO: REPLACE */ + ModuleConfig_AudioConfig audio; } payload_variant; } ModuleConfig; /* Helper constants for enums */ +#define _ModuleConfig_AudioConfig_Audio_Baud_MIN ModuleConfig_AudioConfig_Audio_Baud_CODEC2_DEFAULT +#define _ModuleConfig_AudioConfig_Audio_Baud_MAX ModuleConfig_AudioConfig_Audio_Baud_CODEC2_700B +#define _ModuleConfig_AudioConfig_Audio_Baud_ARRAYSIZE ((ModuleConfig_AudioConfig_Audio_Baud)(ModuleConfig_AudioConfig_Audio_Baud_CODEC2_700B+1)) + #define _ModuleConfig_SerialConfig_Serial_Baud_MIN ModuleConfig_SerialConfig_Serial_Baud_BAUD_DEFAULT #define _ModuleConfig_SerialConfig_Serial_Baud_MAX ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600 #define _ModuleConfig_SerialConfig_Serial_Baud_ARRAYSIZE ((ModuleConfig_SerialConfig_Serial_Baud)(ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600+1)) @@ -156,6 +182,7 @@ extern "C" { /* Initializer values for message structs */ #define ModuleConfig_init_default {0, {ModuleConfig_MQTTConfig_init_default}} #define ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0} +#define ModuleConfig_AudioConfig_init_default {0, 0, 0, 0, _ModuleConfig_AudioConfig_Audio_Baud_MIN} #define ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _ModuleConfig_SerialConfig_Serial_Mode_MIN} #define ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0} #define ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0} @@ -164,6 +191,7 @@ extern "C" { #define ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define ModuleConfig_init_zero {0, {ModuleConfig_MQTTConfig_init_zero}} #define ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0} +#define ModuleConfig_AudioConfig_init_zero {0, 0, 0, 0, _ModuleConfig_AudioConfig_Audio_Baud_MIN} #define ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _ModuleConfig_SerialConfig_Serial_Mode_MIN} #define ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0} #define ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0} @@ -172,6 +200,11 @@ extern "C" { #define ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} /* Field tags (for use in manual encoding/decoding) */ +#define ModuleConfig_AudioConfig_codec2_enabled_tag 1 +#define ModuleConfig_AudioConfig_mic_chan_tag 2 +#define ModuleConfig_AudioConfig_amp_pin_tag 3 +#define ModuleConfig_AudioConfig_ptt_pin_tag 4 +#define ModuleConfig_AudioConfig_bitrate_tag 5 #define ModuleConfig_CannedMessageConfig_rotary1_enabled_tag 1 #define ModuleConfig_CannedMessageConfig_inputbroker_pin_a_tag 2 #define ModuleConfig_CannedMessageConfig_inputbroker_pin_b_tag 3 @@ -222,6 +255,7 @@ extern "C" { #define ModuleConfig_range_test_tag 5 #define ModuleConfig_telemetry_tag 6 #define ModuleConfig_canned_message_tag 7 +#define ModuleConfig_audio_tag 8 /* Struct field encoding specification for nanopb */ #define ModuleConfig_FIELDLIST(X, a) \ @@ -231,7 +265,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,external_notification,payloa X(a, STATIC, ONEOF, MESSAGE, (payload_variant,store_forward,payload_variant.store_forward), 4) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,range_test,payload_variant.range_test), 5) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,telemetry,payload_variant.telemetry), 6) \ -X(a, STATIC, ONEOF, MESSAGE, (payload_variant,canned_message,payload_variant.canned_message), 7) +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,canned_message,payload_variant.canned_message), 7) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,audio,payload_variant.audio), 8) #define ModuleConfig_CALLBACK NULL #define ModuleConfig_DEFAULT NULL #define ModuleConfig_payload_variant_mqtt_MSGTYPE ModuleConfig_MQTTConfig @@ -241,6 +276,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,canned_message,payload_varia #define ModuleConfig_payload_variant_range_test_MSGTYPE ModuleConfig_RangeTestConfig #define ModuleConfig_payload_variant_telemetry_MSGTYPE ModuleConfig_TelemetryConfig #define ModuleConfig_payload_variant_canned_message_MSGTYPE ModuleConfig_CannedMessageConfig +#define ModuleConfig_payload_variant_audio_MSGTYPE ModuleConfig_AudioConfig #define ModuleConfig_MQTTConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, BOOL, enabled, 1) \ @@ -252,6 +288,15 @@ X(a, STATIC, SINGULAR, BOOL, json_enabled, 6) #define ModuleConfig_MQTTConfig_CALLBACK NULL #define ModuleConfig_MQTTConfig_DEFAULT NULL +#define ModuleConfig_AudioConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, BOOL, codec2_enabled, 1) \ +X(a, STATIC, SINGULAR, UINT32, mic_chan, 2) \ +X(a, STATIC, SINGULAR, UINT32, amp_pin, 3) \ +X(a, STATIC, SINGULAR, UINT32, ptt_pin, 4) \ +X(a, STATIC, SINGULAR, UENUM, bitrate, 5) +#define ModuleConfig_AudioConfig_CALLBACK NULL +#define ModuleConfig_AudioConfig_DEFAULT NULL + #define ModuleConfig_SerialConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, BOOL, enabled, 1) \ X(a, STATIC, SINGULAR, BOOL, echo, 2) \ @@ -315,6 +360,7 @@ X(a, STATIC, SINGULAR, BOOL, send_bell, 11) extern const pb_msgdesc_t ModuleConfig_msg; extern const pb_msgdesc_t ModuleConfig_MQTTConfig_msg; +extern const pb_msgdesc_t ModuleConfig_AudioConfig_msg; extern const pb_msgdesc_t ModuleConfig_SerialConfig_msg; extern const pb_msgdesc_t ModuleConfig_ExternalNotificationConfig_msg; extern const pb_msgdesc_t ModuleConfig_StoreForwardConfig_msg; @@ -325,6 +371,7 @@ extern const pb_msgdesc_t ModuleConfig_CannedMessageConfig_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define ModuleConfig_fields &ModuleConfig_msg #define ModuleConfig_MQTTConfig_fields &ModuleConfig_MQTTConfig_msg +#define ModuleConfig_AudioConfig_fields &ModuleConfig_AudioConfig_msg #define ModuleConfig_SerialConfig_fields &ModuleConfig_SerialConfig_msg #define ModuleConfig_ExternalNotificationConfig_fields &ModuleConfig_ExternalNotificationConfig_msg #define ModuleConfig_StoreForwardConfig_fields &ModuleConfig_StoreForwardConfig_msg @@ -333,6 +380,7 @@ extern const pb_msgdesc_t ModuleConfig_CannedMessageConfig_msg; #define ModuleConfig_CannedMessageConfig_fields &ModuleConfig_CannedMessageConfig_msg /* Maximum encoded size of messages (where known) */ +#define ModuleConfig_AudioConfig_size 22 #define ModuleConfig_CannedMessageConfig_size 49 #define ModuleConfig_ExternalNotificationConfig_size 20 #define ModuleConfig_MQTTConfig_size 105 diff --git a/src/mesh/generated/portnums.pb.h b/src/mesh/generated/portnums.pb.h index 3c68e9bb0..ec7b7eaec 100644 --- a/src/mesh/generated/portnums.pb.h +++ b/src/mesh/generated/portnums.pb.h @@ -51,6 +51,9 @@ typedef enum _PortNum { /* Waypoint payloads. Payload is a [Waypoint](/docs/developers/protobufs/api#waypoint) message */ PortNum_WAYPOINT_APP = 8, + /* Audio Payloads. + Encapsulated codec2 packets. On 2.4 GHZ Bandwidths only for now */ + PortNum_AUDIO_APP = 9, /* Provides a 'ping' service that replies to any packet it receives. Also serves as a small example module. */ PortNum_REPLY_APP = 32, @@ -81,7 +84,7 @@ typedef enum _PortNum { PortNum_SIMULATOR_APP = 69, /* Private applications should use portnums >= 256. To simplify initial development and testing you can use "PRIVATE_APP" - in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/Meshtastic-device/blob/master/bin/regen-protos.sh)) */ + in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh)) */ PortNum_PRIVATE_APP = 256, /* ATAK Forwarder Module https://github.com/paulmandal/atak-forwarder */ PortNum_ATAK_FORWARDER = 257, diff --git a/src/mesh/http/ContentHandler.cpp b/src/mesh/http/ContentHandler.cpp index 91f88dda0..82ac8feef 100644 --- a/src/mesh/http/ContentHandler.cpp +++ b/src/mesh/http/ContentHandler.cpp @@ -58,8 +58,6 @@ char contentTypes[][2][32] = {{".txt", "text/plain"}, {".html", "text/html"} {".css", "text/css"}, {".ico", "image/vnd.microsoft.icon"}, {".svg", "image/svg+xml"}, {"", ""}}; -// const char *tarURL = "https://www.casler.org/temp/meshtastic-web.tar"; -// const char *tarURL = "https://api-production-871d.up.railway.app/mirror/webui"; // const char *certificate = NULL; // change this as needed, leave as is for no TLS check (yolo security) // Our API to handle messages to and from the radio. @@ -75,8 +73,8 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer) ResourceNode *nodeAPIv1ToRadio = new ResourceNode("/api/v1/toradio", "PUT", &handleAPIv1ToRadio); ResourceNode *nodeAPIv1FromRadio = new ResourceNode("/api/v1/fromradio", "GET", &handleAPIv1FromRadio); - ResourceNode *nodeHotspotApple = new ResourceNode("/hotspot-detect.html", "GET", &handleHotspot); - ResourceNode *nodeHotspotAndroid = new ResourceNode("/generate_204", "GET", &handleHotspot); + // ResourceNode *nodeHotspotApple = new ResourceNode("/hotspot-detect.html", "GET", &handleHotspot); + // ResourceNode *nodeHotspotAndroid = new ResourceNode("/generate_204", "GET", &handleHotspot); ResourceNode *nodeAdmin = new ResourceNode("/admin", "GET", &handleAdmin); // ResourceNode *nodeAdminSettings = new ResourceNode("/admin/settings", "GET", &handleAdminSettings); @@ -100,8 +98,8 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer) secureServer->registerNode(nodeAPIv1ToRadioOptions); secureServer->registerNode(nodeAPIv1ToRadio); secureServer->registerNode(nodeAPIv1FromRadio); - secureServer->registerNode(nodeHotspotApple); - secureServer->registerNode(nodeHotspotAndroid); + // secureServer->registerNode(nodeHotspotApple); + // secureServer->registerNode(nodeHotspotAndroid); secureServer->registerNode(nodeRestart); secureServer->registerNode(nodeFormUpload); secureServer->registerNode(nodeJsonScanNetworks); @@ -121,8 +119,8 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer) insecureServer->registerNode(nodeAPIv1ToRadioOptions); insecureServer->registerNode(nodeAPIv1ToRadio); insecureServer->registerNode(nodeAPIv1FromRadio); - insecureServer->registerNode(nodeHotspotApple); - insecureServer->registerNode(nodeHotspotAndroid); + // insecureServer->registerNode(nodeHotspotApple); + // insecureServer->registerNode(nodeHotspotAndroid); insecureServer->registerNode(nodeRestart); insecureServer->registerNode(nodeFormUpload); insecureServer->registerNode(nodeJsonScanNetworks); @@ -160,7 +158,7 @@ void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res) res->setHeader("Content-Type", "application/x-protobuf"); res->setHeader("Access-Control-Allow-Origin", "*"); res->setHeader("Access-Control-Allow-Methods", "GET"); - res->setHeader("X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/Meshtastic-protobufs/master/mesh.proto"); + res->setHeader("X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/protobufs/master/mesh.proto"); uint8_t txBuf[MAX_STREAM_BUF_SIZE]; uint32_t len = 1; @@ -204,7 +202,7 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res) res->setHeader("Access-Control-Allow-Headers", "Content-Type"); res->setHeader("Access-Control-Allow-Origin", "*"); res->setHeader("Access-Control-Allow-Methods", "PUT, OPTIONS"); - res->setHeader("X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/Meshtastic-protobufs/master/mesh.proto"); + res->setHeader("X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/protobufs/master/mesh.proto"); if (req->getMethod() == "OPTIONS") { res->setStatusCode(204); // Success with no content @@ -251,7 +249,7 @@ void htmlDeleteDir(const char *dirname) std::vector> *htmlListDir(std::vector> *fileList, const char *dirname, uint8_t levels) { - File root = FSCom.open(dirname); + File root = FSCom.open(dirname, FILE_O_READ); if (!root) { return NULL; } @@ -264,14 +262,27 @@ std::vector> *htmlListDir(std::vector thisFileMap; thisFileMap[strdup("size")] = strdup(String(file.size()).c_str()); +#ifdef ARCH_ESP32 + thisFileMap[strdup("name")] = strdup(String(file.path()).substring(1).c_str()); +#else thisFileMap[strdup("name")] = strdup(String(file.name()).substring(1).c_str()); +#endif if (String(file.name()).substring(1).endsWith(".gz")) { +#ifdef ARCH_ESP32 + String modifiedFile = String(file.path()).substring(1); +#else String modifiedFile = String(file.name()).substring(1); +#endif modifiedFile.remove((modifiedFile.length() - 3), 3); thisFileMap[strdup("nameModified")] = strdup(modifiedFile.c_str()); } @@ -291,7 +302,7 @@ void handleFsBrowseStatic(HTTPRequest *req, HTTPResponse *res) res->setHeader("Access-Control-Allow-Methods", "GET"); using namespace json11; - auto fileList = htmlListDir(new std::vector>(), "/", 10); + auto fileList = htmlListDir(new std::vector>(), "/static", 10); // create json output structure Json filesystemObj = Json::object{ @@ -607,12 +618,8 @@ void handleReport(HTTPRequest *req, HTTPResponse *res) }; // data->wifi - String ipStr; - if (config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN || isSoftAPForced()) { - ipStr = String(WiFi.softAPIP().toString()); - } else { - ipStr = String(WiFi.localIP().toString()); - } + String ipStr = String(WiFi.localIP().toString()); + Json jsonObjWifi = Json::object{{"rssi", String(WiFi.RSSI())}, {"ip", ipStr.c_str()}}; // data->memory diff --git a/src/mesh/http/WebServer.cpp b/src/mesh/http/WebServer.cpp index 48e084ed2..c1844b0cb 100644 --- a/src/mesh/http/WebServer.cpp +++ b/src/mesh/http/WebServer.cpp @@ -55,10 +55,6 @@ static void handleWebResponse() if (isWifiAvailable()) { if (isWebServerReady) { - // We're going to handle the DNS responder here so it - // will be ignored by the NRF boards. - handleDNSResponse(); - if (secureServer) secureServer->loop(); insecureServer->loop(); diff --git a/src/mesh/http/WiFiAPClient.cpp b/src/mesh/http/WiFiAPClient.cpp index 4a4ac05a9..09f5acf48 100644 --- a/src/mesh/http/WiFiAPClient.cpp +++ b/src/mesh/http/WiFiAPClient.cpp @@ -8,7 +8,6 @@ #include "mesh/wifi/WiFiServerAPI.h" #include "mqtt/MQTT.h" #include "target_specific.h" -#include #include #include #include @@ -22,9 +21,6 @@ using namespace concurrency; static void WiFiEvent(WiFiEvent_t event); -// DNS Server for the Captive Portal -DNSServer dnsServer; - // NTP WiFiUDP ntpUDP; @@ -37,8 +33,6 @@ uint8_t wifiDisconnectReason = 0; // Stores our hostname char ourHost[16]; -bool forcedSoftAP = 0; - bool APStartupComplete = 0; static bool needReconnect = true; // If we create our reconnector, run it once at the beginning @@ -88,16 +82,10 @@ static int32_t reconnectWiFi() static Periodic *wifiReconnect; -bool isSoftAPForced() -{ - return forcedSoftAP; -} - bool isWifiAvailable() { - if (config.network.wifi_enabled && ((config.network.wifi_ssid[0]) || forcedSoftAP)) { - + if (config.network.wifi_enabled && (config.network.wifi_ssid[0])) { return true; } else { return false; @@ -161,100 +149,57 @@ static void onNetworkConnected() } // Startup WiFi -bool initWifi(bool forceSoftAP) +bool initWifi() { - forcedSoftAP = forceSoftAP; + if (config.network.wifi_enabled && config.network.wifi_ssid[0]) { - if (config.network.wifi_enabled && ((config.network.wifi_ssid[0]) || forceSoftAP)) { - // if ((radioConfig.has_preferences && config.wifi.ssid[0]) || forceSoftAP) { const char *wifiName = config.network.wifi_ssid; const char *wifiPsw = config.network.wifi_psk; - if (forceSoftAP) { - DEBUG_MSG("WiFi ... Forced AP Mode\n"); - } else if (config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT) { - DEBUG_MSG("WiFi ... AP Mode\n"); - } else if (config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN) { - DEBUG_MSG("WiFi ... Hidden AP Mode\n"); - } else if (config.network.wifi_mode == Config_NetworkConfig_WiFiMode_CLIENT) { - DEBUG_MSG("WiFi ... Client Mode\n"); - } else { - DEBUG_MSG("WiFi ... WiFi Disabled\n"); - } - createSSLCert(); if (!*wifiPsw) // Treat empty password as no password wifiPsw = NULL; - if (*wifiName || forceSoftAP) { - if (config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN || forceSoftAP) { + if (*wifiName) { + uint8_t dmac[6]; + getMacAddr(dmac); + sprintf(ourHost, "Meshtastic-%02x%02x", dmac[4], dmac[5]); - IPAddress apIP(192, 168, 42, 1); - WiFi.onEvent(WiFiEvent); - WiFi.mode(WIFI_AP); - - if (forcedSoftAP) { - const char *softAPssid = "meshtasticAdmin"; - const char *softAPpasswd = "12345678"; - int ok = WiFi.softAP(softAPssid, softAPpasswd); - DEBUG_MSG("Starting (Forced) WIFI AP: ssid=%s, ok=%d\n", softAPssid, ok); - - } else { - - // If AP is configured to be hidden hidden - if (config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN) { - - // The configurations on softAP are from the espresif library - int ok = WiFi.softAP(wifiName, wifiPsw, 1, 1, 4); - DEBUG_MSG("Starting hidden WIFI AP: ssid=%s, ok=%d\n", wifiName, ok); - } else { - int ok = WiFi.softAP(wifiName, wifiPsw); - DEBUG_MSG("Starting WIFI AP: ssid=%s, ok=%d\n", wifiName, ok); - } - int ok = WiFi.softAP(wifiName, wifiPsw); - DEBUG_MSG("Starting WIFI AP: ssid=%s, ok=%d\n", wifiName, ok); - } - - WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); - DEBUG_MSG("MY IP AP ADDRESS: %s\n", WiFi.softAPIP().toString().c_str()); - - // This is needed to improve performance. - esp_wifi_set_ps(WIFI_PS_NONE); // Disable radio power saving - - dnsServer.start(53, "*", apIP); - - } else { - uint8_t dmac[6]; - getMacAddr(dmac); - sprintf(ourHost, "Meshtastic-%02x%02x", dmac[4], dmac[5]); - - WiFi.mode(WIFI_MODE_STA); - WiFi.setHostname(ourHost); - WiFi.onEvent(WiFiEvent); - - // This is needed to improve performance. - esp_wifi_set_ps(WIFI_PS_NONE); // Disable radio power saving - - WiFi.onEvent( - [](WiFiEvent_t event, WiFiEventInfo_t info) { - Serial.print("\nWiFi lost connection. Reason: "); - Serial.println(info.wifi_sta_disconnected.reason); - - /* - If we are disconnected from the AP for some reason, - save the error code. - - For a reference to the codes: - https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html#wi-fi-reason-code - */ - wifiDisconnectReason = info.wifi_sta_disconnected.reason; - }, - WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED); - - DEBUG_MSG("JOINING WIFI soon: ssid=%s\n", wifiName); - wifiReconnect = new Periodic("WifiConnect", reconnectWiFi); + WiFi.mode(WIFI_MODE_STA); + WiFi.setHostname(ourHost); + WiFi.onEvent(WiFiEvent); + WiFi.setAutoReconnect(true); + WiFi.setSleep(false); + if (config.network.eth_mode == Config_NetworkConfig_EthMode_STATIC && config.network.ipv4_config.ip != 0) { + WiFi.config(config.network.ipv4_config.ip, + config.network.ipv4_config.gateway, + config.network.ipv4_config.subnet, + config.network.ipv4_config.dns, + config.network.ipv4_config.dns); // Wifi wants two DNS servers... set both to the same value } + + // This is needed to improve performance. + esp_wifi_set_ps(WIFI_PS_NONE); // Disable radio power saving + + WiFi.onEvent( + [](WiFiEvent_t event, WiFiEventInfo_t info) { + Serial.print("\nWiFi lost connection. Reason: "); + Serial.println(info.wifi_sta_disconnected.reason); + + /* + If we are disconnected from the AP for some reason, + save the error code. + + For a reference to the codes: + https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html#wi-fi-reason-code + */ + wifiDisconnectReason = info.wifi_sta_disconnected.reason; + }, + WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED); + + DEBUG_MSG("JOINING WIFI soon: ssid=%s\n", wifiName); + wifiReconnect = new Periodic("WifiConnect", reconnectWiFi); } return true; } else { @@ -286,8 +231,6 @@ static void WiFiEvent(WiFiEvent_t event) break; case SYSTEM_EVENT_STA_DISCONNECTED: DEBUG_MSG("Disconnected from WiFi access point\n"); - // Event 5 - needReconnect = true; break; case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: @@ -300,6 +243,7 @@ static void WiFiEvent(WiFiEvent_t event) break; case SYSTEM_EVENT_STA_LOST_IP: DEBUG_MSG("Lost IP address and IP address is reset to 0\n"); + needReconnect = true; break; case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: DEBUG_MSG("WiFi Protected Setup (WPS): succeeded in enrollee mode\n"); @@ -315,7 +259,6 @@ static void WiFiEvent(WiFiEvent_t event) break; case SYSTEM_EVENT_AP_START: DEBUG_MSG("WiFi access point started\n"); - onNetworkConnected(); break; case SYSTEM_EVENT_AP_STOP: @@ -356,13 +299,6 @@ static void WiFiEvent(WiFiEvent_t event) } } -void handleDNSResponse() -{ - if (config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN || isSoftAPForced()) { - dnsServer.processNextRequest(); - } -} - uint8_t getWifiDisconnectReason() { return wifiDisconnectReason; diff --git a/src/mesh/http/WiFiAPClient.h b/src/mesh/http/WiFiAPClient.h index 2c6bc912c..9729c24b5 100644 --- a/src/mesh/http/WiFiAPClient.h +++ b/src/mesh/http/WiFiAPClient.h @@ -5,19 +5,14 @@ #include #ifdef ARCH_ESP32 -#include #include #endif /// @return true if wifi is now in use -bool initWifi(bool forceSoftAP); +bool initWifi(); void deinitWifi(); bool isWifiAvailable(); -void handleDNSResponse(); - -bool isSoftAPForced(); - uint8_t getWifiDisconnectReason(); diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 6a10c618a..4a76faf6f 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -295,6 +295,11 @@ void AdminModule::handleSetModuleConfig(const ModuleConfig &c) moduleConfig.has_canned_message = true; moduleConfig.canned_message = c.payload_variant.canned_message; break; + case ModuleConfig_audio_tag: + DEBUG_MSG("Setting module config: Audio\n"); + moduleConfig.has_audio = true; + moduleConfig.audio = c.payload_variant.audio; + break; } service.reloadConfig(SEGMENT_MODULECONFIG); @@ -421,6 +426,11 @@ void AdminModule::handleGetModuleConfig(const MeshPacket &req, const uint32_t co res.get_module_config_response.which_payload_variant = ModuleConfig_canned_message_tag; res.get_module_config_response.payload_variant.canned_message = moduleConfig.canned_message; break; + case AdminMessage_ModuleConfigType_AUDIO_CONFIG: + DEBUG_MSG("Getting module config: Audio\n"); + res.get_module_config_response.which_payload_variant = ModuleConfig_audio_tag; + res.get_module_config_response.payload_variant.audio = moduleConfig.audio; + break; } // NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior. @@ -441,6 +451,10 @@ void AdminModule::handleGetDeviceMetadata(const MeshPacket &req) { DeviceMetadata deviceMetadata; strncpy(deviceMetadata.firmware_version, myNodeInfo.firmware_version, 18); deviceMetadata.device_state_version = DEVICESTATE_CUR_VER; + deviceMetadata.canShutdown = pmu_found || HAS_CPU_SHUTDOWN; + deviceMetadata.hasBluetooth = HAS_BLUETOOTH; + deviceMetadata.hasWifi = HAS_WIFI; + deviceMetadata.hasEthernet = HAS_ETHERNET; r.get_device_metadata_response = deviceMetadata; r.which_payload_variant = AdminMessage_get_device_metadata_response_tag; diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index 7e776f172..e5d371c1b 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -3,18 +3,23 @@ #include "NodeDB.h" #include "RTC.h" #include "Router.h" +#include "buzz/buzz.h" #include "configuration.h" #include +#ifndef PIN_BUZZER +#define PIN_BUZZER false +#endif + //#include /* Documentation: - https://github.com/meshtastic/Meshtastic-device/blob/master/docs/software/modules/ExternalNotificationModule.md + https://github.com/meshtastic/firmware/blob/master/docs/software/modules/ExternalNotificationModule.md This module supports: - https://github.com/meshtastic/Meshtastic-device/issues/654 + https://github.com/meshtastic/firmware/issues/654 Quick reference: @@ -44,7 +49,11 @@ */ // Default configurations +#ifdef EXT_NOTIFY_OUT #define EXT_NOTIFICATION_MODULE_OUTPUT EXT_NOTIFY_OUT +#else +#define EXT_NOTIFICATION_MODULE_OUTPUT 0 +#endif #define EXT_NOTIFICATION_MODULE_OUTPUT_MS 1000 #define ASCII_BELL 0x07 @@ -75,7 +84,9 @@ int32_t ExternalNotificationModule::runOnce() : EXT_NOTIFICATION_MODULE_OUTPUT_MS) < millis()) { DEBUG_MSG("Turning off external notification\n"); - setExternalOff(); + if (output != PIN_BUZZER) { + setExternalOff(); + } } } @@ -84,27 +95,19 @@ int32_t ExternalNotificationModule::runOnce() void ExternalNotificationModule::setExternalOn() { -#ifdef EXT_NOTIFY_OUT externalCurrentState = 1; externalTurnedOn = millis(); - digitalWrite((moduleConfig.external_notification.output - ? moduleConfig.external_notification.output - : EXT_NOTIFICATION_MODULE_OUTPUT), + digitalWrite(output, (moduleConfig.external_notification.active ? true : false)); -#endif } void ExternalNotificationModule::setExternalOff() { -#ifdef EXT_NOTIFY_OUT externalCurrentState = 0; - digitalWrite((moduleConfig.external_notification.output - ? moduleConfig.external_notification.output - : EXT_NOTIFICATION_MODULE_OUTPUT), + digitalWrite(output, (moduleConfig.external_notification.active ? false : true)); -#endif } // -------- @@ -113,11 +116,6 @@ ExternalNotificationModule::ExternalNotificationModule() : SinglePortModule("ExternalNotificationModule", PortNum_TEXT_MESSAGE_APP), concurrency::OSThread( "ExternalNotificationModule") { - // restrict to the admin channel for rx - boundChannel = Channels::gpioChannel; - -#ifdef EXT_NOTIFY_OUT - /* Uncomment the preferences below if you want to use the module without having to configure it from the PythonAPI or WebUI. @@ -130,30 +128,37 @@ ExternalNotificationModule::ExternalNotificationModule() // moduleConfig.external_notification.alert_bell = 1; // moduleConfig.external_notification.output_ms = 1000; // moduleConfig.external_notification.output = 13; + + if (moduleConfig.external_notification.alert_message) { + // restrict to the gpio channel for rx + boundChannel = Channels::gpioChannel; + } if (moduleConfig.external_notification.enabled) { DEBUG_MSG("Initializing External Notification Module\n"); - // Set the direction of a pin - pinMode((moduleConfig.external_notification.output - ? moduleConfig.external_notification.output - : EXT_NOTIFICATION_MODULE_OUTPUT), - OUTPUT); + output = moduleConfig.external_notification.output + ? moduleConfig.external_notification.output + : EXT_NOTIFICATION_MODULE_OUTPUT; - // Turn off the pin - setExternalOff(); + if (output != PIN_BUZZER) { + // Set the direction of a pin + DEBUG_MSG("Using Pin %i in digital mode\n", output); + pinMode(output, OUTPUT); + // Turn off the pin + setExternalOff(); + } else{ + DEBUG_MSG("Using Pin %i in PWM mode\n", output); + } } else { DEBUG_MSG("External Notification Module Disabled\n"); enabled = false; } -#endif } ProcessMessage ExternalNotificationModule::handleReceived(const MeshPacket &mp) { -#ifdef EXT_NOTIFY_OUT - if (moduleConfig.external_notification.enabled) { if (getFrom(&mp) != nodeDB.getNodeNum()) { @@ -165,21 +170,28 @@ ProcessMessage ExternalNotificationModule::handleReceived(const MeshPacket &mp) DEBUG_MSG("externalNotificationModule - Notification Bell\n"); for (int i = 0; i < p.payload.size; i++) { if (p.payload.bytes[i] == ASCII_BELL) { - setExternalOn(); + if (output != PIN_BUZZER) { + setExternalOn(); + } else { + playBeep(); + } } } } if (moduleConfig.external_notification.alert_message) { DEBUG_MSG("externalNotificationModule - Notification Module\n"); - setExternalOn(); + if (output != PIN_BUZZER) { + setExternalOn(); + } else { + playBeep(); + } } } } else { DEBUG_MSG("External Notification Module Disabled\n"); } -#endif return ProcessMessage::CONTINUE; // Let others look at this message also if they want } diff --git a/src/modules/ExternalNotificationModule.h b/src/modules/ExternalNotificationModule.h index a671d67c2..b5ab64b3c 100644 --- a/src/modules/ExternalNotificationModule.h +++ b/src/modules/ExternalNotificationModule.h @@ -12,6 +12,8 @@ */ class ExternalNotificationModule : public SinglePortModule, private concurrency::OSThread { + uint32_t output = 0; + public: ExternalNotificationModule(); diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp index 986a375df..d24fa8f26 100644 --- a/src/modules/Modules.cpp +++ b/src/modules/Modules.cpp @@ -19,6 +19,9 @@ #ifdef ARCH_ESP32 #include "modules/esp32/RangeTestModule.h" #include "modules/esp32/StoreForwardModule.h" +#ifdef USE_SX1280 +#include "modules/esp32/AudioModule.h" +#endif #endif #if defined(ARCH_ESP32) || defined(ARCH_NRF52) #include "modules/ExternalNotificationModule.h" @@ -65,17 +68,16 @@ void setupModules() #endif #ifdef ARCH_ESP32 // Only run on an esp32 based device. - - /* - Maintained by MC Hamster (Jm Casler) jm@casler.org - */ +#ifdef USE_SX1280 + new AudioModule(); +#endif new ExternalNotificationModule(); storeForwardModule = new StoreForwardModule(); new RangeTestModule(); #elif defined(ARCH_NRF52) -new ExternalNotificationModule(); + new ExternalNotificationModule(); #endif // NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra acks diff --git a/src/modules/Telemetry/Sensor/BME280Sensor.cpp b/src/modules/Telemetry/Sensor/BME280Sensor.cpp index 15ec18007..4b6a50091 100644 --- a/src/modules/Telemetry/Sensor/BME280Sensor.cpp +++ b/src/modules/Telemetry/Sensor/BME280Sensor.cpp @@ -16,6 +16,14 @@ int32_t BME280Sensor::runOnce() { return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; } status = bme280.begin(nodeTelemetrySensorsMap[sensorType]); + + bme280.setSampling( Adafruit_BME280::MODE_FORCED, + Adafruit_BME280::SAMPLING_X1, // Temp. oversampling + Adafruit_BME280::SAMPLING_X1, // Pressure oversampling + Adafruit_BME280::SAMPLING_X1, // Humidity oversampling + Adafruit_BME280::FILTER_OFF, + Adafruit_BME280::STANDBY_MS_1000); + return initI2CSensor(); } @@ -23,6 +31,7 @@ void BME280Sensor::setup() { } bool BME280Sensor::getMetrics(Telemetry *measurement) { DEBUG_MSG("BME280Sensor::getMetrics\n"); + bme280.takeForcedMeasurement(); measurement->variant.environment_metrics.temperature = bme280.readTemperature(); measurement->variant.environment_metrics.relative_humidity = bme280.readHumidity(); measurement->variant.environment_metrics.barometric_pressure = bme280.readPressure() / 100.0F; diff --git a/src/modules/Telemetry/Sensor/BME680Sensor.cpp b/src/modules/Telemetry/Sensor/BME680Sensor.cpp index 474c376dd..a9171facf 100644 --- a/src/modules/Telemetry/Sensor/BME680Sensor.cpp +++ b/src/modules/Telemetry/Sensor/BME680Sensor.cpp @@ -14,25 +14,19 @@ int32_t BME680Sensor::runOnce() { if (!hasSensor()) { return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; } - status = bme680.begin(nodeTelemetrySensorsMap[sensorType]); + status = bme680.begin(nodeTelemetrySensorsMap[sensorType]); + return initI2CSensor(); } -void BME680Sensor::setup() -{ - // Set up oversampling and filter initialization - bme680.setTemperatureOversampling(BME680_OS_8X); - bme680.setHumidityOversampling(BME680_OS_2X); - bme680.setPressureOversampling(BME680_OS_4X); - bme680.setIIRFilterSize(BME680_FILTER_SIZE_3); - bme680.setGasHeater(320, 150); // 320*C for 150 ms -} +void BME680Sensor::setup() { } bool BME680Sensor::getMetrics(Telemetry *measurement) { - measurement->variant.environment_metrics.temperature = bme680.readTemperature(); - measurement->variant.environment_metrics.relative_humidity = bme680.readHumidity(); - measurement->variant.environment_metrics.barometric_pressure = bme680.readPressure() / 100.0F; - measurement->variant.environment_metrics.gas_resistance = bme680.readGas() / 1000.0; + bme680.performReading(); + measurement->variant.environment_metrics.temperature = bme680.temperature; + measurement->variant.environment_metrics.relative_humidity = bme680.humidity; + measurement->variant.environment_metrics.barometric_pressure = bme680.pressure / 100.0F; + measurement->variant.environment_metrics.gas_resistance = bme680.gas_resistance / 1000.0; return true; } \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/BMP280Sensor.cpp b/src/modules/Telemetry/Sensor/BMP280Sensor.cpp index 4fecdf1a8..917c40d6f 100644 --- a/src/modules/Telemetry/Sensor/BMP280Sensor.cpp +++ b/src/modules/Telemetry/Sensor/BMP280Sensor.cpp @@ -16,6 +16,13 @@ int32_t BMP280Sensor::runOnce() { return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; } status = bmp280.begin(nodeTelemetrySensorsMap[sensorType]); + + bmp280.setSampling( Adafruit_BMP280::MODE_FORCED, + Adafruit_BMP280::SAMPLING_X1, // Temp. oversampling + Adafruit_BMP280::SAMPLING_X1, // Pressure oversampling + Adafruit_BMP280::FILTER_OFF, + Adafruit_BMP280::STANDBY_MS_1000); + return initI2CSensor(); } @@ -23,6 +30,7 @@ void BMP280Sensor::setup() { } bool BMP280Sensor::getMetrics(Telemetry *measurement) { DEBUG_MSG("BMP280Sensor::getMetrics\n"); + bmp280.takeForcedMeasurement(); measurement->variant.environment_metrics.temperature = bmp280.readTemperature(); measurement->variant.environment_metrics.barometric_pressure = bmp280.readPressure() / 100.0F; diff --git a/src/modules/esp32/AudioModule.cpp b/src/modules/esp32/AudioModule.cpp new file mode 100644 index 000000000..7147db43c --- /dev/null +++ b/src/modules/esp32/AudioModule.cpp @@ -0,0 +1,240 @@ +#include "configuration.h" +#include "AudioModule.h" +#include "MeshService.h" +#include "NodeDB.h" +#include "RTC.h" +#include "Router.h" +#include "FSCommon.h" + +#include + +/* + AudioModule + A interface to send raw codec2 audio data over the mesh network. Based on the example code from the ESP32_codec2 project. + https://github.com/deulis/ESP32_Codec2 + + Codec 2 is a low-bitrate speech audio codec (speech coding) + that is patent free and open source develop by David Grant Rowe. + http://www.rowetel.com/ and https://github.com/drowe67/codec2 + + Basic Usage: + 1) Enable the module by setting audio.codec2_enabled to 1. + 2) Set the pins (audio.mic_pin / audio.amp_pin) for your preferred microphone and amplifier GPIO pins. + On tbeam, recommend to use: + audio.mic_chan 7 (GPIO 35) + audio.amp_pin 25 (GPIO 25) + 3) Set audio.timeout to the amount of time to wait before we consider + your voice stream as "done". + 4) Set audio.bitrate to the desired codec2 rate (CODEC2_3200, CODEC2_2400, CODEC2_1600, CODEC2_1400, CODEC2_1300, CODEC2_1200, CODEC2_700, CODEC2_700B) + + KNOWN PROBLEMS + * Until the module is initilized by the startup sequence, the amp_pin pin is in a floating + state. This may produce a bit of "noise". + * Will not work on NRF and the Linux device targets. +*/ + +#define AMIC 7 +#define AAMP 25 +#define PTT_PIN 39 + +#define AUDIO_MODULE_RX_BUFFER 128 +#define AUDIO_MODULE_DATA_MAX Constants_DATA_PAYLOAD_LEN +#define AUDIO_MODULE_MODE 7 // 700B +#define AUDIO_MODULE_ACK 1 + +#if defined(ARCH_ESP32) && defined(USE_SX1280) + +AudioModule *audioModule; + +ButterworthFilter hp_filter(240, 8000, ButterworthFilter::ButterworthFilter::Highpass, 1); + +//int16_t 1KHz sine test tone +int16_t Sine1KHz[8] = { -21210 , -30000, -21210, 0 , 21210 , 30000 , 21210, 0 }; +int Sine1KHz_index = 0; + +uint8_t rx_raw_audio_value = 127; + +AudioModule::AudioModule() : SinglePortModule("AudioModule", PortNum_AUDIO_APP), concurrency::OSThread("AudioModule") { + audio_fifo.init(); +} + +void AudioModule::run_codec2() +{ + if (state == State::tx) + { + for (int i = 0; i < ADC_BUFFER_SIZE; i++) + speech[i] = (int16_t)hp_filter.Update((float)speech[i]); + + codec2_encode(codec2_state, tx_encode_frame + tx_encode_frame_index, speech); + + //increment the pointer where the encoded frame must be saved + tx_encode_frame_index += 8; + + //If it is the 5th time then we have a ready trasnmission frame + if (tx_encode_frame_index == ENCODE_FRAME_SIZE) + { + tx_encode_frame_index = 0; + //Transmit it + sendPayload(); + } + } + if (state == State::rx) //Receiving + { + //Make a cycle to get each codec2 frame from the received frame + for (int i = 0; i < ENCODE_FRAME_SIZE; i += 8) + { + //Decode the codec2 frame + codec2_decode(codec2_state, output_buffer, rx_encode_frame + i); + + // Add to the audio buffer the 320 samples resulting of the decode of the codec2 frame. + for (int g = 0; g < ADC_BUFFER_SIZE; g++) + audio_fifo.put(output_buffer[g]); + } + } + state = State::standby; +} + +void AudioModule::handleInterrupt() +{ + audioModule->onTimer(); +} + +void AudioModule::onTimer() +{ + if (state == State::tx) { + adc_buffer[adc_buffer_index++] = (16 * adc1_get_raw(mic_chan)) - 32768; + + //If you want to test with a 1KHz tone, comment the line above and descomment the three lines below + + // adc_buffer[adc_buffer_index++] = Sine1KHz[Sine1KHz_index++]; + // if (Sine1KHz_index >= 8) + // Sine1KHz_index = 0; + + if (adc_buffer_index == ADC_BUFFER_SIZE) { + adc_buffer_index = 0; + memcpy((void*)speech, (void*)adc_buffer, 2 * ADC_BUFFER_SIZE); + audioModule->setIntervalFromNow(0); // process buffer immediately + } + } else if (state == State::rx) { + + int16_t v; + + //Get a value from audio_fifo and convert it to 0 - 255 to play it in the ADC + //If none value is available the DAC will play the last one that was read, that's + //why the rx_raw_audio_value variable is a global one. + if (audio_fifo.get(&v)) + rx_raw_audio_value = (uint8_t)((v + 32768) / 256); + + //Play + dacWrite(moduleConfig.audio.amp_pin ? moduleConfig.audio.amp_pin : AAMP, rx_raw_audio_value); + } +} + +int32_t AudioModule::runOnce() +{ + if (moduleConfig.audio.codec2_enabled) { + + if (firstTime) { + + DEBUG_MSG("Initializing ADC on Channel %u\n", moduleConfig.audio.mic_chan ? moduleConfig.audio.mic_chan : AMIC); + + mic_chan = moduleConfig.audio.mic_chan ? (adc1_channel_t)(int)moduleConfig.audio.mic_chan : (adc1_channel_t)AMIC; + adc1_config_width(ADC_WIDTH_12Bit); + adc1_config_channel_atten(mic_chan, ADC_ATTEN_DB_6); + + // Start a timer at 8kHz to sample the ADC and play the audio on the DAC. + uint32_t cpufreq = getCpuFrequencyMhz(); + switch (cpufreq){ + case 160: + adcTimer = timerBegin(3, 1000, true); // 160 MHz / 1000 = 160KHz + break; + case 240: + adcTimer = timerBegin(3, 1500, true); // 240 MHz / 1500 = 160KHz + break; + case 320: + adcTimer = timerBegin(3, 2000, true); // 320 MHz / 2000 = 160KHz + break; + case 80: + default: + adcTimer = timerBegin(3, 500, true); // 80 MHz / 500 = 160KHz + break; + } + timerAttachInterrupt(adcTimer, &AudioModule::handleInterrupt, true); + timerAlarmWrite(adcTimer, 20, true); // Interrupts when counter == 20, 8.000 times a second + timerAlarmEnable(adcTimer); + + DEBUG_MSG("Initializing DAC on Pin %u\n", moduleConfig.audio.amp_pin ? moduleConfig.audio.amp_pin : AAMP); + DEBUG_MSG("Initializing PTT on Pin %u\n", moduleConfig.audio.ptt_pin ? moduleConfig.audio.ptt_pin : PTT_PIN); + + // Configure PTT input + pinMode(moduleConfig.audio.ptt_pin ? moduleConfig.audio.ptt_pin : PTT_PIN, INPUT_PULLUP); + + state = State::rx; + + DEBUG_MSG("Setting up codec2 in mode %u\n", moduleConfig.audio.bitrate ? moduleConfig.audio.bitrate : AUDIO_MODULE_MODE); + + codec2_state = codec2_create(moduleConfig.audio.bitrate ? moduleConfig.audio.bitrate : AUDIO_MODULE_MODE); + codec2_set_lpc_post_filter(codec2_state, 1, 0, 0.8, 0.2); + + firstTime = 0; + } else { + // Check if we have a PTT press + if (digitalRead(moduleConfig.audio.ptt_pin ? moduleConfig.audio.ptt_pin : PTT_PIN) == LOW) { + // PTT pressed, recording + state = State::tx; + } + if (state != State::standby) { + run_codec2(); + } + } + + return 100; + } else { + DEBUG_MSG("Audio Module Disabled\n"); + + return INT32_MAX; + } +} + +MeshPacket *AudioModule::allocReply() +{ + + auto reply = allocDataPacket(); // Allocate a packet for sending + + return reply; +} + +void AudioModule::sendPayload(NodeNum dest, bool wantReplies) +{ + MeshPacket *p = allocReply(); + p->to = dest; + p->decoded.want_response = wantReplies; + + p->want_ack = AUDIO_MODULE_ACK; + + p->decoded.payload.size = ENCODE_FRAME_SIZE; + memcpy(p->decoded.payload.bytes, tx_encode_frame, p->decoded.payload.size); + + service.sendToMesh(p); +} + +ProcessMessage AudioModule::handleReceived(const MeshPacket &mp) +{ + if (moduleConfig.audio.codec2_enabled) { + auto &p = mp.decoded; + if (getFrom(&mp) != nodeDB.getNodeNum()) { + if (p.payload.size == ENCODE_FRAME_SIZE) { + memcpy(rx_encode_frame, p.payload.bytes, p.payload.size); + state = State::rx; + audioModule->setIntervalFromNow(0); + run_codec2(); + } else { + DEBUG_MSG("Invalid payload size %u != %u\n", p.payload.size, ENCODE_FRAME_SIZE); + } + } + } + + return ProcessMessage::CONTINUE; +} + +#endif \ No newline at end of file diff --git a/src/modules/esp32/AudioModule.h b/src/modules/esp32/AudioModule.h new file mode 100644 index 000000000..d82af4d43 --- /dev/null +++ b/src/modules/esp32/AudioModule.h @@ -0,0 +1,68 @@ +#pragma once + +#include "SinglePortModule.h" +#include "concurrency/OSThread.h" +#include "configuration.h" +#include "NodeDB.h" +#include +#include +#include +#if defined(ARCH_ESP32) && defined(USE_SX1280) +#include +#include +#include +#endif + +#define ADC_BUFFER_SIZE 320 // 40ms of voice in 8KHz sampling frequency +#define ENCODE_FRAME_SIZE 40 // 5 codec2 frames of 8 bytes each + +class AudioModule : public SinglePortModule, private concurrency::OSThread +{ +#if defined(ARCH_ESP32) && defined(USE_SX1280) + bool firstTime = 1; + hw_timer_t* adcTimer = NULL; + uint16_t adc_buffer[ADC_BUFFER_SIZE] = {}; + int16_t speech[ADC_BUFFER_SIZE] = {}; + int16_t output_buffer[ADC_BUFFER_SIZE] = {}; + unsigned char rx_encode_frame[ENCODE_FRAME_SIZE] = {}; + unsigned char tx_encode_frame[ENCODE_FRAME_SIZE] = {}; + int tx_encode_frame_index = 0; + FastAudioFIFO audio_fifo; + uint16_t adc_buffer_index = 0; + adc1_channel_t mic_chan = (adc1_channel_t)0; + struct CODEC2* codec2_state = NULL; + + enum State + { + standby, rx, tx + }; + volatile State state = State::tx; + + public: + AudioModule(); + + /** + * Send our payload into the mesh + */ + void sendPayload(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false); + + protected: + virtual int32_t runOnce() override; + + static void handleInterrupt(); + + void onTimer(); + + void run_codec2(); + + virtual MeshPacket *allocReply() override; + + /** Called to handle a particular incoming message + * @return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for it + */ + virtual ProcessMessage handleReceived(const MeshPacket &mp) override; +#endif +}; + +extern AudioModule *audioModule; + diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 7deba4668..194683939 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -8,7 +8,9 @@ #include "mesh/generated/mqtt.pb.h" #include "mesh/generated/telemetry.pb.h" #include "sleep.h" +#if HAS_WIFI #include +#endif #include #include @@ -67,22 +69,25 @@ void MQTT::onPublish(char *topic, byte *payload, unsigned int length) DEBUG_MSG("Invalid MQTT service envelope, topic %s, len %u!\n", topic, length); } } else { - pb_decode_from_bytes(payload, length, ServiceEnvelope_fields, &e); - if (strcmp(e.gateway_id, owner.id) == 0) - DEBUG_MSG("Ignoring downlink message we originally sent.\n"); - else { - if (e.packet) { - DEBUG_MSG("Received MQTT topic %s, len=%u\n", topic, length); - MeshPacket *p = packetPool.allocCopy(*e.packet); + if (!pb_decode_from_bytes(payload, length, ServiceEnvelope_fields, &e)) { + DEBUG_MSG("Invalid MQTT service envelope, topic %s, len %u!\n", topic, length); + return; + }else { + if (strcmp(e.gateway_id, owner.id) == 0) + DEBUG_MSG("Ignoring downlink message we originally sent.\n"); + else { + if (e.packet) { + DEBUG_MSG("Received MQTT topic %s, len=%u\n", topic, length); + MeshPacket *p = packetPool.allocCopy(*e.packet); - // ignore messages sent by us or if we don't have the channel key - if (router && p->from != nodeDB.getNodeNum() && perhapsDecode(p)) - router->enqueueReceivedMessage(p); - else - packetPool.release(p); + // ignore messages sent by us or if we don't have the channel key + if (router && p->from != nodeDB.getNodeNum() && perhapsDecode(p)) + router->enqueueReceivedMessage(p); + else + packetPool.release(p); + } } } - // make sure to free both strings and the MeshPacket (passing in NULL is acceptable) free(e.channel_id); free(e.gateway_id); @@ -105,6 +110,11 @@ MQTT::MQTT() : concurrency::OSThread("mqtt"), pubSub(mqttClient) // preflightSleepObserver.observe(&preflightSleep); } +bool MQTT::connected() +{ + return pubSub.connected(); +} + void MQTT::reconnect() { if (wantsLink()) { @@ -189,7 +199,13 @@ bool MQTT::wantsLink() const } } +#if HAS_WIFI return hasChannel && WiFi.isConnected(); +#endif +#if HAS_ETHERNET + return hasChannel && (Ethernet.linkStatus() == LinkON); +#endif + return false; } int32_t MQTT::runOnce() @@ -346,9 +362,9 @@ std::string MQTT::downstreamPacketToJson(MeshPacket *mp) msgPayload = Json::object{ {"time", (int)decoded->time}, {"pos_timestamp", (int)decoded->timestamp}, - {"latitude_i", decoded->latitude_i}, - {"longitude_i", decoded->longitude_i}, - {"altitude", decoded->altitude} + {"latitude_i", (int)decoded->latitude_i}, + {"longitude_i", (int)decoded->longitude_i}, + {"altitude", (int)decoded->altitude} }; } else { DEBUG_MSG("Error decoding protobuf for position message!\n"); @@ -371,8 +387,8 @@ std::string MQTT::downstreamPacketToJson(MeshPacket *mp) {"description", decoded->description}, {"expire", (int)decoded->expire}, {"locked", decoded->locked}, - {"latitude_i", decoded->latitude_i}, - {"longitude_i", decoded->longitude_i}, + {"latitude_i", (int)decoded->latitude_i}, + {"longitude_i", (int)decoded->longitude_i}, }; } else { DEBUG_MSG("Error decoding protobuf for position message!\n"); diff --git a/src/mqtt/MQTT.h b/src/mqtt/MQTT.h index 9d80c7d91..c8381574c 100644 --- a/src/mqtt/MQTT.h +++ b/src/mqtt/MQTT.h @@ -5,7 +5,12 @@ #include "concurrency/OSThread.h" #include "mesh/Channels.h" #include +#if HAS_WIFI #include +#endif +#if HAS_ETHERNET +#include +#endif /** * Our wrapper/singleton for sending/receiving MQTT "udp" packets. This object isolates the MQTT protocol implementation from @@ -16,7 +21,12 @@ class MQTT : private concurrency::OSThread // supposedly the current version is busted: // http://www.iotsharing.com/2017/08/how-to-use-esp32-mqtts-with-mqtts-mosquitto-broker-tls-ssl.html // WiFiClientSecure wifiClient; +#if HAS_WIFI WiFiClient mqttClient; +#endif +#if HAS_ETHERNET + EthernetClient mqttClient; +#endif PubSubClient pubSub; // instead we supress sleep from our runOnce() callback @@ -38,6 +48,8 @@ class MQTT : private concurrency::OSThread /** Attempt to connect to server if necessary */ void reconnect(); + + bool connected(); protected: virtual int32_t runOnce() override; diff --git a/src/network-stubs.cpp b/src/network-stubs.cpp new file mode 100644 index 000000000..0119fa1be --- /dev/null +++ b/src/network-stubs.cpp @@ -0,0 +1,27 @@ +#include "configuration.h" + +#if (HAS_WIFI == 0) + +bool initWifi() { + return false; +} + +void deinitWifi() {} + +bool isWifiAvailable() { + return false; +} + +#endif + +#if (HAS_ETHERNET == 0) + +bool initEthernet() { + return false; +} + +bool isEthernetAvailable() { + return false; +} + +#endif diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp index b2a4e3970..c74c73316 100644 --- a/src/nimble/NimbleBluetooth.cpp +++ b/src/nimble/NimbleBluetooth.cpp @@ -12,7 +12,6 @@ NimBLECharacteristic *fromNumCharacteristic; NimBLEServer *bleServer; static bool passkeyShowing; -static uint32_t doublepressed; class BluetoothPhoneAPI : public PhoneAPI { @@ -71,12 +70,8 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks { virtual uint32_t onPassKeyRequest() { uint32_t passkey = config.bluetooth.fixed_pin; - - if (doublepressed > 0 && (doublepressed + (30 * 1000)) > millis()) { - DEBUG_MSG("User has set BLE pairing mode to fixed-pin\n"); - config.bluetooth.mode = Config_BluetoothConfig_PairingMode_FIXED_PIN; - nodeDB.saveToDisk(SEGMENT_CONFIG); - } else if (config.bluetooth.mode == Config_BluetoothConfig_PairingMode_RANDOM_PIN) { + + if (config.bluetooth.mode == Config_BluetoothConfig_PairingMode_RANDOM_PIN) { DEBUG_MSG("Using random passkey\n"); // This is the passkey to be entered on peer - we pick a number >100,000 to ensure 6 digits passkey = random(100000, 999999); @@ -202,24 +197,3 @@ void clearNVS() ESP.restart(); #endif } - -void disablePin() -{ - DEBUG_MSG("User Override, disabling bluetooth pin requirement\n"); - // keep track of when it was pressed, so we know it was within X seconds - - // Flash the LED - setLed(true); - delay(100); - setLed(false); - delay(100); - setLed(true); - delay(100); - setLed(false); - delay(100); - setLed(true); - delay(100); - setLed(false); - - doublepressed = millis(); -} diff --git a/src/nimble/NimbleBluetooth.h b/src/nimble/NimbleBluetooth.h index 5592b6d69..ec0fe0841 100644 --- a/src/nimble/NimbleBluetooth.h +++ b/src/nimble/NimbleBluetooth.h @@ -15,4 +15,3 @@ class NimbleBluetooth void setBluetoothEnable(bool on); void clearNVS(); -void disablePin(); diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index 527f2947e..00d221691 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -70,6 +70,8 @@ #define HW_VENDOR HardwareModel_TLORA_V1_1P3 #elif defined(TLORA_V2_1_16) #define HW_VENDOR HardwareModel_TLORA_V2_1_1P6 +#elif defined(TLORA_V2_1_18) + #define HW_VENDOR HardwareModel_TLORA_V2_1_1P8 #elif defined(GENIEBLOCKS) #define HW_VENDOR HardwareModel_GENIEBLOCKS #elif defined(PRIVATE_HW) @@ -80,6 +82,8 @@ #define HW_VENDOR HardwareModel_M5STACK #elif defined(STATION_G1) #define HW_VENDOR HardwareModel_STATION_G1 +#elif defined(DR_DEV) + #define HW_VENDOR HardwareModel_DR_DEV #endif // diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h index 63e173434..986a864c9 100644 --- a/src/platform/nrf52/architecture.h +++ b/src/platform/nrf52/architecture.h @@ -26,6 +26,9 @@ #ifndef HAS_RADIO #define HAS_RADIO 1 #endif +#ifdef HAS_CPU_SHUTDOWN + #define HAS_CPU_SHUTDOWN 1 +#endif // // set HW_VENDOR @@ -42,7 +45,7 @@ #define HW_VENDOR HardwareModel_T_ECHO #elif defined(NORDIC_PCA10059) #define HW_VENDOR HardwareModel_NRF52840_PCA10059 -#elif defined(PRIVATE_HW) +#elif defined(PRIVATE_HW) || defined(FEATHER_DIY) #define HW_VENDOR HardwareModel_PRIVATE_HW #else #define HW_VENDOR HardwareModel_NRF52_UNKNOWN diff --git a/src/shutdown.h b/src/shutdown.h index f37339641..3927825fb 100644 --- a/src/shutdown.h +++ b/src/shutdown.h @@ -13,11 +13,12 @@ void powerCommandsCheck() #elif defined(ARCH_NRF52) NVIC_SystemReset(); #else - DEBUG_MSG("FIXME implement reboot for this platform"); + rebootAtMsec = -1; + DEBUG_MSG("FIXME implement reboot for this platform. Skipping for now.\n"); #endif } -#if defined(ARCH_NRF52) +#if defined(ARCH_NRF52) || defined(HAS_PMU) if (shutdownAtMsec) { screen->startShutdownScreen(); playBeep(); diff --git a/src/sleep.cpp b/src/sleep.cpp index 055cf770d..390ab7f65 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -263,8 +263,8 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r #ifdef BUTTON_PIN gpio_wakeup_enable((gpio_num_t)BUTTON_PIN, GPIO_INTR_LOW_LEVEL); // when user presses, this button goes low #endif -#ifdef RF95_IRQ_GPIO - gpio_wakeup_enable((gpio_num_t)RF95_IRQ_GPIO, GPIO_INTR_HIGH_LEVEL); // RF95 interrupt, active high +#ifdef RF95_IRQ + gpio_wakeup_enable((gpio_num_t)RF95_IRQ, GPIO_INTR_HIGH_LEVEL); // RF95 interrupt, active high #endif #ifdef PMU_IRQ // wake due to PMU can happen repeatedly if there is no battery installed or the battery fills diff --git a/src/wifi-stubs.cpp b/src/wifi-stubs.cpp deleted file mode 100644 index faf58b620..000000000 --- a/src/wifi-stubs.cpp +++ /dev/null @@ -1,19 +0,0 @@ -//#include "mesh/wifi/WebServer.h" -#include "configuration.h" - -#ifndef ARCH_ESP32 - -//#include "mesh/wifi/WiFiAPClient.h" - -bool initWifi(bool forceSoftAP) { - return false; -} - -void deinitWifi() {} - -bool isWifiAvailable() -{ - return false; -} - -#endif diff --git a/variants/diy/dr-dev/variant.h b/variants/diy/dr-dev/variant.h new file mode 100644 index 000000000..7d0625907 --- /dev/null +++ b/variants/diy/dr-dev/variant.h @@ -0,0 +1,71 @@ +// Initialize i2c bus on sd_dat and esp_led pins, respectively. We need a bus to not hang on boot +#define HAS_SCREEN 0 +#define I2C_SDA 4 +#define I2C_SCL 5 + +// GPS +#undef GPS_RX_PIN +#define GPS_RX_PIN NOT_A_PIN +#define HAS_GPS 0 + +#define BUTTON_PIN 13 // The middle button GPIO on the T-Beam +#define BUTTON_NEED_PULLUP +#define EXT_NOTIFY_OUT 12 // Overridden default pin to use for Ext Notify Module (#975). + +#define LORA_DIO0 NOT_A_PIN // a No connect on the SX1262/SX1268 module +#define LORA_RESET NOT_A_PIN // RST for SX1276, and for SX1262/SX1268 +#define LORA_DIO3 NOT_A_PIN // Not connected on PCB, but internally on the SX1262/SX1268, if DIO3 is high the TXCO is enabled + +// In transmitting, set TXEN as high communication level,RXEN pin is low level; +// In receiving, set RXEN as high communication level, TXEN is lowlevel; +// Before powering off, set TXEN、RXEN as low level. + +#undef RF95_SCK +#define RF95_SCK 18 +#undef RF95_MISO +#define RF95_MISO 19 +#undef RF95_MOSI +#define RF95_MOSI 23 + +// PINS FOR THE 900M22S + +#define LORA_DIO1 26 // IRQ for SX1262/SX1268 +#define LORA_DIO2 22 // BUSY for SX1262/SX1268 +#define LORA_TXEN NOT_A_PIN // Input - RF switch TX control, connecting external MCU IO or DIO2, valid in high level +#define LORA_RXEN 17 // Input - RF switch RX control, connecting external MCU IO, valid in high level +#undef RF95_NSS +#define RF95_NSS 16 +#define SX126X_BUSY 22 +#define SX126X_CS 16 + + +// PINS FOR THE 900M30S +/* +#define LORA_DIO1 27 // IRQ for SX1262/SX1268 +#define LORA_DIO2 35 // BUSY for SX1262/SX1268 +#define LORA_TXEN NOT_A_PIN // Input - RF switch TX control, connecting external MCU IO or DIO2, valid in high level +#define LORA_RXEN 21 // Input - RF switch RX control, connecting external MCU IO, valid in high level +#undef RF95_NSS +#define RF95_NSS 33 +#define SX126X_BUSY 35 +#define SX126X_CS 33 +*/ + +// RX/TX for RFM95/SX127x +#define RF95_RXEN LORA_RXEN +#define RF95_TXEN LORA_TXEN +// #define RF95_TCXO + +// common pinouts for SX126X modules + +#define SX126X_DIO1 LORA_DIO1 +#define SX126X_RESET LORA_RESET +#define SX126X_RXEN LORA_RXEN +#define SX126X_TXEN LORA_TXEN + +// supported modules list +//#define USE_RF95 // RFM95/SX127x +#define USE_SX1262 +//#define USE_SX1268 +//#define USE_LLCC68 +#define SX126X_E22 diff --git a/variants/feather_diy/platformio.ini b/variants/feather_diy/platformio.ini new file mode 100644 index 000000000..84c582ab0 --- /dev/null +++ b/variants/feather_diy/platformio.ini @@ -0,0 +1,11 @@ +; The very slick RAK wireless RAK 4631 / 4630 board - Unified firmware for 5005/19003, with or without OLED RAK 1921 +[env:feather_diy] +extends = nrf52840_base +board = adafruit_feather_nrf52840 +build_flags = ${nrf52840_base.build_flags} -Ivariants/feather_diy -Dfeather_diy +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/feather_diy> +lib_deps = + ${nrf52840_base.lib_deps} +debug_tool = jlink +; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) +;upload_protocol = jlink \ No newline at end of file diff --git a/variants/feather_diy/variant.cpp b/variants/feather_diy/variant.cpp new file mode 100644 index 000000000..7311c9019 --- /dev/null +++ b/variants/feather_diy/variant.cpp @@ -0,0 +1,24 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. All right reserved. + Copyright (c) 2016 Sandeep Mistry All right reserved. + Copyright (c) 2018, Adafruit Industries (adafruit.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "variant.h" +#include "nrf.h" +#include "wiring_constants.h" +#include "wiring_digital.h" diff --git a/variants/feather_diy/variant.h b/variants/feather_diy/variant.h new file mode 100644 index 000000000..92128add2 --- /dev/null +++ b/variants/feather_diy/variant.h @@ -0,0 +1,119 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. All right reserved. + Copyright (c) 2016 Sandeep Mistry All right reserved. + Copyright (c) 2018, Adafruit Industries (adafruit.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _VARIANT_FEATHER_DIY_ +#define _VARIANT_FEATHER_DIY_ + +/** Master clock frequency */ +#define VARIANT_MCK (64000000ul) + +#define USE_LFXO // Board uses 32khz crystal for LF +// define USE_LFRC // Board uses RC for LF + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "WVariant.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Number of pins defined in PinDescription array +#define PINS_COUNT (48) +#define NUM_DIGITAL_PINS (48) +#define NUM_ANALOG_INPUTS (6) +#define NUM_ANALOG_OUTPUTS (0) + +#define WIRE_INTERFACES_COUNT 1 + +#define PIN_WIRE_SDA (0 + 12) //P0.12 22 +#define PIN_WIRE_SCL (0 + 11) //P0.12 23 + +#define PIN_LED1 (32 + 15) //P1.15 3 +#define PIN_LED2 (32 + 10) //P1.10 4 + +#define LED_BUILTIN PIN_LED1 + +#define LED_GREEN PIN_LED2 // Actually red +#define LED_BLUE PIN_LED1 + +#define LED_STATE_ON 1 // State when LED is litted + +#define BUTTON_PIN (32 + 2) //P1.02 7 + +/* + * Serial interfaces + */ +#define PIN_SERIAL1_RX (0 + 24) //P0.24 1 +#define PIN_SERIAL1_TX (0 + 25) //P0.25 0 + +#define PIN_SERIAL2_RX (-1) +#define PIN_SERIAL2_TX (-1) + +#define SPI_INTERFACES_COUNT 1 + +#define PIN_SPI_MISO (0 + 15) //P0.15 24 +#define PIN_SPI_MOSI (0 + 13) //P0.13 25 +#define PIN_SPI_SCK (0 + 14) //P0.14 26 + +#define SS 2 + +#define LORA_DIO0 -1 // a No connect on the SX1262/SX1268 module +#define LORA_RESET (32 + 9) //P1.09 13 // RST for SX1276, and for SX1262/SX1268 +#define LORA_DIO1 (0 + 6) //P0.06 11 // IRQ for SX1262/SX1268 +#define LORA_DIO2 (0 + 8) //P0.08 12 // BUSY for SX1262/SX1268 +#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262/SX1268, if DIO3 is high the TXCO is enabled + +#define RF95_SCK SCK +#define RF95_MISO MI +#define RF95_MOSI MO +#define RF95_NSS SS + +// enables 3.3V periphery like GPS or IO Module +#define PIN_3V3_EN (-1) + +#undef USE_EINK + +// supported modules list +#define USE_SX1262 + +// common pinouts for SX126X modules +#define SX126X_CS RF95_NSS // NSS for SX126X +#define SX126X_DIO1 LORA_DIO1 +#define SX126X_BUSY LORA_DIO2 +#define SX126X_RESET LORA_RESET +#define SX126X_RXEN (0 + 27) //P0.27 10 +#define SX126X_TXEN (0 + 26) //P0.26 9 + +#ifdef EBYTE_E22 +// Internally the TTGO module hooks the SX126x-DIO2 in to control the TX/RX switch +// (which is the default for the sx1262interface code) +#define SX126X_E22 +#endif + +#ifdef __cplusplus +} +#endif + +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ + +#endif diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index d8e2ba3e9..3521a43ff 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -3,10 +3,12 @@ extends = nrf52840_base board = wiscore_rak4631 build_flags = ${nrf52840_base.build_flags} -Ivariants/rak4631 -D RAK_4631 -build_src_filter = ${nrf52_base.build_src_filter} +<../variants/rak4631> +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/rak4631> + + lib_deps = ${nrf52840_base.lib_deps} + ${networking_base.lib_deps} melopero/Melopero RV3028@^1.1.0 + https://github.com/meshtastic/RAK13800-W5100S.git#b680706eb8006cd62c919ac74c8af1950eb82c81 debug_tool = jlink ; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) ;upload_protocol = jlink \ No newline at end of file diff --git a/variants/rak4631/variant.h b/variants/rak4631/variant.h index 3648b8510..904491b6a 100644 --- a/variants/rak4631/variant.h +++ b/variants/rak4631/variant.h @@ -185,6 +185,9 @@ static const uint8_t SCK = PIN_SPI_SCK; #define SX126X_RXEN (37) #define SX126X_E22 // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3 +// enables 3.3V periphery like GPS or IO Module +#define PIN_3V3_EN (34) + // RAK1910 GPS module // If using the wisblock GPS module and pluged into Port A on WisBlock base // IO1 is hooked to PPS (pin 12 on header) = gpio 17 @@ -192,7 +195,7 @@ static const uint8_t SCK = PIN_SPI_SCK; // Therefore must be 1 to keep peripherals powered // Power is on the controllable 3V3_S rail // #define PIN_GPS_RESET (34) -#define PIN_GPS_EN (34) +#define PIN_GPS_EN PIN_3V3_EN #define PIN_GPS_PPS (17) // Pulse per second input from the GPS #define GPS_RX_PIN PIN_SERIAL1_RX @@ -226,6 +229,12 @@ static const uint8_t SCK = PIN_SPI_SCK; #define HAS_RTC 1 +#define HAS_ETHERNET 1 + +#define PIN_ETHERNET_RESET 21 +#define PIN_ETHERNET_SS PIN_EINK_CS +#define ETH_SPI_PORT SPI1 + #ifdef __cplusplus } #endif diff --git a/variants/rak4631_epaper/variant.h b/variants/rak4631_epaper/variant.h index df68dac41..cf1b8b07d 100644 --- a/variants/rak4631_epaper/variant.h +++ b/variants/rak4631_epaper/variant.h @@ -185,6 +185,9 @@ static const uint8_t SCK = PIN_SPI_SCK; #define SX126X_RXEN (37) #define SX126X_E22 // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3 +// enables 3.3V periphery like GPS or IO Module +#define PIN_3V3_EN (34) + // RAK1910 GPS module // If using the wisblock GPS module and pluged into Port A on WisBlock base // IO1 is hooked to PPS (pin 12 on header) = gpio 17 @@ -192,7 +195,7 @@ static const uint8_t SCK = PIN_SPI_SCK; // Therefore must be 1 to keep peripherals powered // Power is on the controllable 3V3_S rail // #define PIN_GPS_RESET (34) -#define PIN_GPS_EN (34) +#define PIN_GPS_EN PIN_3V3_EN #define PIN_GPS_PPS (17) // Pulse per second input from the GPS #define GPS_RX_PIN PIN_SERIAL1_RX diff --git a/variants/tlora_v2/variant.h b/variants/tlora_v2/variant.h index 1bff09fb0..0c854e37a 100644 --- a/variants/tlora_v2/variant.h +++ b/variants/tlora_v2/variant.h @@ -8,8 +8,6 @@ #define I2C_SDA 21 // I2C pins for this board #define I2C_SCL 22 -#define RESET_OLED 16 // If defined, this pin will be used to reset the display controller - #define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost #define LED_PIN 25 // If defined we will blink this LED #define BUTTON_PIN \ @@ -21,4 +19,4 @@ #define LORA_DIO0 26 // a No connect on the SX1262 module #define LORA_RESET 14 #define LORA_DIO1 35 // Not really used -#define LORA_DIO2 34 // Not really used \ No newline at end of file +#define LORA_DIO2 34 // Not really used diff --git a/variants/tlora_v2_1_18/platformio.ini b/variants/tlora_v2_1_18/platformio.ini new file mode 100644 index 000000000..4160be5de --- /dev/null +++ b/variants/tlora_v2_1_18/platformio.ini @@ -0,0 +1,8 @@ +[env:tlora-v2-1-1.8] +extends = esp32_base +board = ttgo-lora32-v21 +lib_deps = + ${esp32_base.lib_deps} + caveman99/ESP32 Codec2@^1.0.1 +build_flags = + ${esp32_base.build_flags} -D TLORA_V2_1_18 -I variants/tlora_v2_1_18 \ No newline at end of file diff --git a/variants/tlora_v2_1_18/variant.h b/variants/tlora_v2_1_18/variant.h new file mode 100644 index 000000000..cd693a3d2 --- /dev/null +++ b/variants/tlora_v2_1_18/variant.h @@ -0,0 +1,33 @@ +#undef GPS_RX_PIN +#undef GPS_TX_PIN +#define GPS_RX_PIN 15 // per @der_bear on the forum, 36 is incorrect for this board type and 15 is a better pick +#define GPS_TX_PIN 13 + +#define EXT_NOTIFY_OUT 2 // Default pin to use for Ext Notify Module. + +#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +// ratio of voltage divider = 2.0 (R42=100k, R43=100k) +#define ADC_MULTIPLIER 2.11 // 2.0 + 10% for correction of display undervoltage. + +#define I2C_SDA 21 // I2C pins for this board +#define I2C_SCL 22 + +// #define RESET_OLED 16 // If defined, this pin will be used to reset the display controller. Crashes on newer ESP-IDF and not needed per schematic + +#define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost +#define LED_PIN 25 // If defined we will blink this LED +#define BUTTON_PIN 12 // If defined, this will be used for user button presses, + +#define BUTTON_NEED_PULLUP + +#define USE_SX1280 +#define LORA_DIO0 26 // a No connect on the SX1262 module +#define LORA_RESET 23 + +#define SX128X_CS 18 // FIXME - we really should define LORA_CS instead +#define SX128X_DIO1 33 +#define SX128X_BUSY 32 +#define SX128X_RESET LORA_RESET +#define SX128X_E22 // Not really an E22 but TTGO seems to be trying to clone that +// Internally the TTGO module hooks the SX1280-DIO2 in to control the TX/RX switch (which is the default for the sx1280interface +// code) diff --git a/version.properties b/version.properties index 750a9609f..303bb9783 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] -major = 1 -minor = 3 -build = 47 +major = 2 +minor = 0 +build = 3