diff --git a/.github/ISSUE_TEMPLATE/Bug Report.yml b/.github/ISSUE_TEMPLATE/Bug Report.yml index 795c1b1a0..d4e00b4ed 100644 --- a/.github/ISSUE_TEMPLATE/Bug Report.yml +++ b/.github/ISSUE_TEMPLATE/Bug Report.yml @@ -40,10 +40,12 @@ body: - T-Echo - Rak4631 - Rak11200 + - Rak11310 - Heltec v1 - Heltec v2 - Heltec v2.1 - Heltec V3 + - Raspberry Pi Pico (W) - Relay v1 - Relay v2 - DIY diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 9ef8f77c6..32f280a04 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -7,7 +7,8 @@ is appreciated." This will allow other devs to potentially save you time by not accidentially duplicating work etc... - Please do not check in files that don't have real changes - Please do not reformat lines that you didn't have to change the code on -- We recommend using the [Visual Studio Code](https://platformio.org/install/ide?install=vscode) editor and the 'clang-format' extension, - because automatically follows our indentation rules and it's auto reformatting will not cause spurious changes to lines. +- We recommend using the [Visual Studio Code](https://platformio.org/install/ide?install=vscode) editor along with the ['Trunk Check' extension](https://marketplace.visualstudio.com/items?itemName=trunk.io) (WSL2 is required on windows), + because it automatically follows our indentation rules and its auto reformatting will not cause spurious changes to lines. - If your PR fixes a bug, mention "fixes #bugnum" somewhere in your pull request description. - If your other co-developers have comments on your PR please tweak as needed. +- Please also enable "Allow edits by maintainers". diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index 6194bfe69..1cac7479b 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -33,6 +33,7 @@ jobs: - board: m5stack-coreink - board: tbeam-s3-core - board: tlora-t3s3-v1 + #- board: rak11310 runs-on: ubuntu-latest steps: @@ -103,16 +104,17 @@ jobs: with: board: ${{ matrix.board }} - # build-rpi2040: - # strategy: - # fail-fast: false - # max-parallel: 2 - # matrix: - # include: - # - board: pico - # uses: ./.github/workflows/build_rpi2040.yml - # with: - # board: ${{ matrix.board }} + build-rpi2040: + strategy: + fail-fast: false + max-parallel: 2 + matrix: + include: + - board: pico + - board: rak11310 + uses: ./.github/workflows/build_rpi2040.yml + with: + board: ${{ matrix.board }} build-native: runs-on: ubuntu-latest @@ -148,12 +150,14 @@ jobs: release/device-*.bat - name: Docker login + if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }} uses: docker/login-action@v2 with: username: meshtastic password: ${{ secrets.DOCKER_TOKEN }} - name: Docker setup + if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }} uses: docker/setup-buildx-action@v2 - name: Docker build and push tagged versions @@ -166,7 +170,7 @@ jobs: tags: meshtastic/device-simulator:${{ steps.version.outputs.version }} - name: Docker build and push - if: github.ref == 'refs/heads/master' + if: ${{ github.ref == 'refs/heads/master' && github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }} uses: docker/build-push-action@v3 with: context: . @@ -186,7 +190,8 @@ jobs: gather-artifacts: runs-on: ubuntu-latest - needs: [build-esp32, build-esp32-s3, build-nrf52, build-native] #, build-rpi2040] + needs: + [build-esp32, build-esp32-s3, build-nrf52, build-native, build-rpi2040] steps: - name: Checkout code uses: actions/checkout@v3 diff --git a/.gitignore b/.gitignore index be3ca3397..89f8ee065 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ __pycache__ venv/ release/ .vscode/extensions.json +/compile_commands.json diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini index 961b41852..62a943ece 100644 --- a/arch/esp32/esp32.ini +++ b/arch/esp32/esp32.ini @@ -37,7 +37,7 @@ lib_deps = ${environmental_base.lib_deps} https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2 h2zero/NimBLE-Arduino@^1.4.0 - jgromes/RadioLib@^6.0.0 + jgromes/RadioLib@^6.1.0 https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f @@ -55,4 +55,4 @@ lib_ignore = ; customize the partition table ; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables -board_build.partitions = partition-table.csv +board_build.partitions = partition-table.csv \ No newline at end of file diff --git a/arch/nrf52/nrf52.ini b/arch/nrf52/nrf52.ini index d471e24c5..f44054f24 100644 --- a/arch/nrf52/nrf52.ini +++ b/arch/nrf52/nrf52.ini @@ -13,8 +13,7 @@ build_src_filter = lib_deps= ${arduino_base.lib_deps} - jgromes/RadioLib@^6.0.0 + jgromes/RadioLib@^6.1.0 lib_ignore = - BluetoothOTA - + BluetoothOTA \ No newline at end of file diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index 6d15e9178..b39974853 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -22,9 +22,9 @@ lib_deps = ${env.lib_deps} ${networking_base.lib_deps} rweather/Crypto@^0.4.0 - jgromes/RadioLib@^6.0.0 + jgromes/RadioLib@6.1.0 build_flags = ${arduino_base.build_flags} -fPIC - -Isrc/platform/portduino + -Isrc/platform/portduino \ No newline at end of file diff --git a/arch/rp2040/rp2040.ini b/arch/rp2040/rp2040.ini index 6f5449ae6..52fba9cba 100644 --- a/arch/rp2040/rp2040.ini +++ b/arch/rp2040/rp2040.ini @@ -1,7 +1,8 @@ ; Common settings for rp2040 Processor based targets [rp2040_base] -platform = https://github.com/maxgerhardt/platform-raspberrypi.git#9f8c10e50b5acd18e7bfd32638199c655be73a5b +platform = https://github.com/maxgerhardt/platform-raspberrypi.git#0c33219f53faa035e188925ea1324f472e8b93d2 extends = arduino_base +platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.2.2 board_build.core = earlephilhower board_build.filesystem_size = 0.5m @@ -19,5 +20,5 @@ lib_ignore = lib_deps = ${arduino_base.lib_deps} ${environmental_base.lib_deps} - jgromes/RadioLib@^6.0.0 - https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b + jgromes/RadioLib@^6.1.0 + https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b \ No newline at end of file diff --git a/arch/stm32/stm32wl5e.ini b/arch/stm32/stm32wl5e.ini index b610bf40b..819ecc31c 100644 --- a/arch/stm32/stm32wl5e.ini +++ b/arch/stm32/stm32wl5e.ini @@ -1,20 +1,29 @@ [stm32wl5e_base] -platform = platformio/ststm32@^15.4.1 +platform_packages = platformio/framework-arduinoststm32 @ https://github.com/stm32duino/Arduino_Core_STM32.git#6e3f9910d0122e82a6c3438507dfac3d2fd80a39 +platform = ststm32 board = generic_wl5e framework = arduino build_type = debug -build_flags = + +build_flags = ${arduino_base.build_flags} -Isrc/platform/stm32wl -g + -DconfigUSE_CMSIS_RTOS_V2=1 + -DVECT_TAB_OFFSET=0x08000000 + +build_src_filter = + ${arduino_base.build_src_filter} - - - - - - - - - - - - - -build_src_filter = - ${arduino_base.build_src_filter} - - - - - - - - - - - - - - +board_upload.offset_address = 0x08000000 +upload_protocol = stlink lib_deps = ${env.lib_deps} - jgromes/RadioLib@^6.0.0 + jgromes/RadioLib@^6.1.0 https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b + https://github.com/littlefs-project/littlefs.git#v2.5.1 + https://github.com/stm32duino/STM32FreeRTOS.git#10.3.1 lib_ignore = - https://github.com/mathertel/OneButton#2.1.0 + https://github.com/mathertel/OneButton#2.1.0 \ No newline at end of file diff --git a/boards/generic_wl5e.json b/boards/generic_wl5e.json index 433c55b59..5c4bc24a7 100644 --- a/boards/generic_wl5e.json +++ b/boards/generic_wl5e.json @@ -20,7 +20,7 @@ "maximum_ram_size": 65536, "maximum_size": 262144, "protocol": "cmsis-dap", - "protocols": ["cmsis-dap"] + "protocols": ["cmsis-dap", "stlink"] }, "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32wl-series.html", "vendor": "ST" diff --git a/boards/wiscore_rak11300.json b/boards/wiscore_rak11300.json new file mode 100644 index 000000000..19beee74d --- /dev/null +++ b/boards/wiscore_rak11300.json @@ -0,0 +1,40 @@ +{ + "build": { + "arduino": { + "earlephilhower": { + "boot2_source": "boot2_w25q080_2_padded_checksum.S", + "usb_vid": "0x2E8A", + "usb_pid": "0x000A" + } + }, + "core": "earlephilhower", + "cpu": "cortex-m0plus", + "extra_flags": "-DARDUINO_GENERIC_RP2040 -DRASPBERRY_PI_PICO -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250", + "f_cpu": "133000000L", + "hwids": [ + ["0x2E8A", "0x00C0"], + ["0x2E8A", "0x000A"] + ], + "mcu": "rp2040", + "variant": "WisBlock_RAK11300_Board" + }, + "debug": { + "jlink_device": "RP2040_M0_0", + "openocd_target": "rp2040.cfg", + "svd_path": "rp2040.svd" + }, + "frameworks": ["arduino"], + "name": "WisBlock RAK11300", + "upload": { + "maximum_ram_size": 270336, + "maximum_size": 2097152, + "require_upload_port": true, + "native_usb": true, + "use_1200bps_touch": true, + "wait_for_upload_port": false, + "protocol": "picotool", + "protocols": ["cmsis-dap", "raspberrypi-swd", "picotool", "picoprobe"] + }, + "url": "https://docs.rakwireless.com/", + "vendor": "RAKwireless" +} diff --git a/platformio.ini b/platformio.ini index 498a05b97..b580d7160 100644 --- a/platformio.ini +++ b/platformio.ini @@ -2,7 +2,7 @@ ; https://docs.platformio.org/page/projectconf.html [platformio] -default_envs = tbeam +;default_envs = tbeam ;default_envs = pico ;default_envs = tbeam-s3-core ;default_envs = tbeam0.7 @@ -25,6 +25,7 @@ default_envs = tbeam ;default_envs = meshtastic-dr-dev ;default_envs = m5stack-coreink ;default_envs = rak4631 +default_envs = wio-e5 extra_configs = arch/*/*.ini @@ -55,6 +56,12 @@ build_flags = -Wno-missing-field-initializers -DRADIOLIB_EXCLUDE_MORSE -DRADIOLIB_EXCLUDE_RTTY -DRADIOLIB_EXCLUDE_SSTV + -DRADIOLIB_EXCLUDE_AX25 + -DRADIOLIB_EXCLUDE_DIRECT_RECEIVE + -DRADIOLIB_EXCLUDE_BELL + -DRADIOLIB_EXCLUDE_PAGER + -DRADIOLIB_EXCLUDE_FSK4 + -DRADIOLIB_EXCLUDE_APRS monitor_speed = 115200 @@ -102,7 +109,7 @@ lib_deps = adafruit/Adafruit Unified Sensor@^1.1.9 adafruit/Adafruit BMP280 Library@^2.6.6 adafruit/Adafruit BME280 Library@^2.2.2 - boschsensortec/BSEC2 Software Library@^1.3.2200 + https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.5.2400 boschsensortec/BME68x Sensor Library@^1.1.40407 adafruit/Adafruit MCP9808 Library@^2.0.0 adafruit/Adafruit INA260 Library@^1.5.0 diff --git a/protobufs b/protobufs index d7327c3de..5f3daac5f 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit d7327c3de2a1dbd9ebb90864c703f97c673a4fc7 +Subproject commit 5f3daac5fabdfe2a0561395fed0ba11a38ba3e7e diff --git a/src/ButtonThread.h b/src/ButtonThread.h index 0a8b2afa5..135d727c2 100644 --- a/src/ButtonThread.h +++ b/src/ButtonThread.h @@ -51,7 +51,7 @@ class ButtonThread : public concurrency::OSThread pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP_SENSE); #endif userButton.attachClick(userButtonPressed); - userButton.setClickTicks(300); + userButton.setClickMs(300); userButton.attachDuringLongPress(userButtonPressedLong); userButton.attachDoubleClick(userButtonDoublePressed); userButton.attachMultiClick(userButtonMultiPressed); @@ -157,7 +157,7 @@ class ButtonThread : public concurrency::OSThread digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW); #endif screen->print("Sent ad-hoc ping\n"); - service.refreshMyNodeInfo(); + service.refreshLocalMeshNode(); service.sendNetworkPing(NODENUM_BROADCAST, true); } @@ -196,4 +196,4 @@ class ButtonThread : public concurrency::OSThread } }; -} // namespace concurrency +} // namespace concurrency \ No newline at end of file diff --git a/src/FSCommon.cpp b/src/FSCommon.cpp index cc99caed8..150391237 100644 --- a/src/FSCommon.cpp +++ b/src/FSCommon.cpp @@ -57,7 +57,7 @@ bool renameFile(const char *pathFrom, const char *pathTo) #endif } -void listDir(const char *dirname, uint8_t levels, boolean del = false) +void listDir(const char *dirname, uint8_t levels, bool del = false) { #ifdef FSCom #if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO)) diff --git a/src/FSCommon.h b/src/FSCommon.h index 98d3911d7..ef1d3e4c1 100644 --- a/src/FSCommon.h +++ b/src/FSCommon.h @@ -13,6 +13,13 @@ #define FILE_O_READ "r" #endif +#if defined(ARCH_STM32WL) +#include "platform/stm32wl/InternalFileSystem.h" // STM32WL version +#define FSCom InternalFS +#define FSBegin() FSCom.begin() +using namespace LittleFS_Namespace; +#endif + #if defined(ARCH_RP2040) // RP2040 #include "LittleFS.h" @@ -42,6 +49,6 @@ using namespace Adafruit_LittleFS_Namespace; void fsInit(); bool copyFile(const char *from, const char *to); bool renameFile(const char *pathFrom, const char *pathTo); -void listDir(const char *dirname, uint8_t levels, boolean del); +void listDir(const char *dirname, uint8_t levels, bool del); void rmDir(const char *dirname); void setupSDCard(); \ No newline at end of file diff --git a/src/GPSStatus.h b/src/GPSStatus.h index 6b760385f..ed3b3fc14 100644 --- a/src/GPSStatus.h +++ b/src/GPSStatus.h @@ -55,7 +55,7 @@ class GPSStatus : public Status #ifdef GPS_EXTRAVERBOSE LOG_WARN("Using fixed latitude\n"); #endif - meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); + meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum()); return node->position.latitude_i; } else { return p.latitude_i; @@ -68,7 +68,7 @@ class GPSStatus : public Status #ifdef GPS_EXTRAVERBOSE LOG_WARN("Using fixed longitude\n"); #endif - meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); + meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum()); return node->position.longitude_i; } else { return p.longitude_i; @@ -81,7 +81,7 @@ class GPSStatus : public Status #ifdef GPS_EXTRAVERBOSE LOG_WARN("Using fixed altitude\n"); #endif - meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); + meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum()); return node->position.altitude; } else { return p.altitude; @@ -149,4 +149,4 @@ class GPSStatus : public Status } // namespace meshtastic -extern meshtastic::GPSStatus *gpsStatus; +extern meshtastic::GPSStatus *gpsStatus; \ No newline at end of file diff --git a/src/Power.cpp b/src/Power.cpp index c3a34d620..37d80a31f 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -6,7 +6,6 @@ #include "main.h" #include "sleep.h" #include "utils.h" -static const char *TAG = "ADCmod"; #ifdef DEBUG_HEAP_MQTT #include "mqtt/MQTT.h" @@ -31,16 +30,25 @@ RTC_NOINIT_ATTR uint64_t RTC_reg_b; #endif // BAT_MEASURE_ADC_UNIT esp_adc_cal_characteristics_t *adc_characs = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t)); - +#ifndef ADC_ATTENUATION static const adc_atten_t atten = ADC_ATTEN_DB_11; +#else +static const adc_atten_t atten = ADC_ATTENUATION; +#endif #endif // BATTERY_PIN && ARCH_ESP32 +#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) +INA260Sensor ina260Sensor; +INA219Sensor ina219Sensor; +#endif + #ifdef HAS_PMU #include "XPowersAXP192.tpp" #include "XPowersAXP2101.tpp" #include "XPowersLibInterface.hpp" XPowersLibInterface *PMU = NULL; #else + // Copy of the base class defined in axp20x.h. // I'd rather not inlude axp20x.h as it brings Wire dependency. class HasBatteryLevel @@ -126,6 +134,13 @@ class AnalogBatteryLevel : public HasBatteryLevel virtual uint16_t getBattVoltage() override { +#if defined(HAS_TELEMETRY) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU) + if (hasINA()) { + LOG_DEBUG("Using INA on I2C addr 0x%x for device battery voltage\n", config.power.device_battery_ina_address); + return getINAVoltage(); + } +#endif + #ifndef ADC_MULTIPLIER #define ADC_MULTIPLIER 2.0 #endif @@ -244,6 +259,35 @@ class AnalogBatteryLevel : public HasBatteryLevel const float fullVolt = BAT_FULLVOLT, emptyVolt = BAT_EMPTYVOLT, chargingVolt = BAT_CHARGINGVOLT, noBatVolt = BAT_NOBATVOLT; float last_read_value = 0.0; uint32_t last_read_time_ms = 0; + +#if defined(HAS_TELEMETRY) && !defined(ARCH_PORTDUINO) + uint16_t getINAVoltage() + { + if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219] == config.power.device_battery_ina_address) { + return ina219Sensor.getBusVoltageMv(); + } else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260] == config.power.device_battery_ina_address) { + return ina260Sensor.getBusVoltageMv(); + } + return 0; + } + + bool hasINA() + { + if (!config.power.device_battery_ina_address) { + return false; + } + if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219] == config.power.device_battery_ina_address) { + if (!ina219Sensor.isInitialized()) + return ina219Sensor.runOnce() > 0; + return ina219Sensor.isRunning(); + } else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260] == config.power.device_battery_ina_address) { + if (!ina260Sensor.isInitialized()) + return ina260Sensor.runOnce() > 0; + return ina260Sensor.isRunning(); + } + return false; + } +#endif }; AnalogBatteryLevel analogLevel; @@ -292,12 +336,16 @@ bool Power::analogInit() esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_characs); // show ADC characterization base if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) { - ESP_LOGI(TAG, "ADC characterization based on Two Point values stored in eFuse"); + LOG_INFO("ADCmod: ADC characterization based on Two Point values stored in eFuse\n"); } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) { - ESP_LOGI(TAG, "ADC characterization based on reference voltage stored in eFuse"); + LOG_INFO("ADCmod: ADC characterization based on reference voltage stored in eFuse\n"); } else { - ESP_LOGI(TAG, "ADC characterization based on default reference voltage"); + LOG_INFO("ADCmod: ADC characterization based on default reference voltage\n"); } +#if defined(HELTEC_V3) || defined(HELTEC_WSL_V3) + pinMode(37, OUTPUT); // needed for P channel mosfet to work + digitalWrite(37, LOW); +#endif #endif // ARCH_ESP32 #ifdef ARCH_NRF52 @@ -604,82 +652,80 @@ bool Power::axpChipInit() } else if (PMU->getChipModel() == XPOWERS_AXP2101) { /*The alternative version of T-Beam 1.1 differs from T-Beam V1.1 in that it uses an AXP2101 power chip*/ -#if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) - // Unuse power channel - PMU->disablePowerOutput(XPOWERS_DCDC2); - PMU->disablePowerOutput(XPOWERS_DCDC3); - PMU->disablePowerOutput(XPOWERS_DCDC4); - PMU->disablePowerOutput(XPOWERS_DCDC5); - PMU->disablePowerOutput(XPOWERS_ALDO1); - PMU->disablePowerOutput(XPOWERS_ALDO4); - PMU->disablePowerOutput(XPOWERS_BLDO1); - PMU->disablePowerOutput(XPOWERS_BLDO2); - PMU->disablePowerOutput(XPOWERS_DLDO1); - PMU->disablePowerOutput(XPOWERS_DLDO2); + if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) { + // Unuse power channel + PMU->disablePowerOutput(XPOWERS_DCDC2); + PMU->disablePowerOutput(XPOWERS_DCDC3); + PMU->disablePowerOutput(XPOWERS_DCDC4); + PMU->disablePowerOutput(XPOWERS_DCDC5); + PMU->disablePowerOutput(XPOWERS_ALDO1); + PMU->disablePowerOutput(XPOWERS_ALDO4); + PMU->disablePowerOutput(XPOWERS_BLDO1); + PMU->disablePowerOutput(XPOWERS_BLDO2); + PMU->disablePowerOutput(XPOWERS_DLDO1); + PMU->disablePowerOutput(XPOWERS_DLDO2); - // GNSS RTC PowerVDD 3300mV - PMU->setPowerChannelVoltage(XPOWERS_VBACKUP, 3300); - PMU->enablePowerOutput(XPOWERS_VBACKUP); + // GNSS RTC PowerVDD 3300mV + PMU->setPowerChannelVoltage(XPOWERS_VBACKUP, 3300); + PMU->enablePowerOutput(XPOWERS_VBACKUP); - // ESP32 VDD 3300mV - // ! No need to set, automatically open , Don't close it - // PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300); - // PMU->setProtectedChannel(XPOWERS_DCDC1); + // ESP32 VDD 3300mV + // ! No need to set, automatically open , Don't close it + // PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300); + // PMU->setProtectedChannel(XPOWERS_DCDC1); - // LoRa VDD 3300mV - PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); - PMU->enablePowerOutput(XPOWERS_ALDO2); + // LoRa VDD 3300mV + PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO2); - // GNSS VDD 3300mV - PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); - PMU->enablePowerOutput(XPOWERS_ALDO3); + // GNSS VDD 3300mV + PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO3); + } else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) { + // t-beam s3 core + /** + * gnss module power channel + * The default ALDO4 is off, you need to turn on the GNSS power first, otherwise it will be invalid during + * initialization + */ + PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO4); -#elif (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) - // t-beam s3 core - /** - * gnss module power channel - * The default ALDO4 is off, you need to turn on the GNSS power first, otherwise it will be invalid during - * initialization - */ - PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300); - PMU->enablePowerOutput(XPOWERS_ALDO4); + // lora radio power channel + PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO3); - // lora radio power channel - PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); - PMU->enablePowerOutput(XPOWERS_ALDO3); + // m.2 interface + PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300); + PMU->enablePowerOutput(XPOWERS_DCDC3); - // m.2 interface - PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300); - PMU->enablePowerOutput(XPOWERS_DCDC3); + /** + * ALDO2 cannot be turned off. + * It is a necessary condition for sensor communication. + * It must be turned on to properly access the sensor and screen + * It is also responsible for the power supply of PCF8563 + */ + PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO2); - /** - * ALDO2 cannot be turned off. - * It is a necessary condition for sensor communication. - * It must be turned on to properly access the sensor and screen - * It is also responsible for the power supply of PCF8563 - */ - PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); - PMU->enablePowerOutput(XPOWERS_ALDO2); + // 6-axis , magnetometer ,bme280 , oled screen power channel + PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO1); - // 6-axis , magnetometer ,bme280 , oled screen power channel - PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300); - PMU->enablePowerOutput(XPOWERS_ALDO1); + // sdcard power channle + PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300); + PMU->enablePowerOutput(XPOWERS_BLDO1); - // sdcard power channle - PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300); - PMU->enablePowerOutput(XPOWERS_BLDO1); + // PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 3300); + // PMU->enablePowerOutput(XPOWERS_DCDC4); - // PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 3300); - // PMU->enablePowerOutput(XPOWERS_DCDC4); - - // not use channel - PMU->disablePowerOutput(XPOWERS_DCDC2); // not elicited - PMU->disablePowerOutput(XPOWERS_DCDC5); // not elicited - PMU->disablePowerOutput(XPOWERS_DLDO1); // Invalid power channel, it does not exist - PMU->disablePowerOutput(XPOWERS_DLDO2); // Invalid power channel, it does not exist - PMU->disablePowerOutput(XPOWERS_VBACKUP); - -#endif + // not use channel + PMU->disablePowerOutput(XPOWERS_DCDC2); // not elicited + PMU->disablePowerOutput(XPOWERS_DCDC5); // not elicited + PMU->disablePowerOutput(XPOWERS_DLDO1); // Invalid power channel, it does not exist + PMU->disablePowerOutput(XPOWERS_DLDO2); // Invalid power channel, it does not exist + PMU->disablePowerOutput(XPOWERS_VBACKUP); + } // disable all axp chip interrupt PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ); diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 6804242c2..e2cf94258 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -35,7 +35,7 @@ static bool isPowered() static void sdsEnter() { - LOG_INFO("Enter state: SDS\n"); + LOG_DEBUG("Enter state: SDS\n"); // FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw doDeepSleep(getConfiguredOrDefaultMs(config.power.sds_secs)); } @@ -44,7 +44,7 @@ extern Power *power; static void shutdownEnter() { - LOG_INFO("Enter state: SHUTDOWN\n"); + LOG_DEBUG("Enter state: SHUTDOWN\n"); power->shutdown(); } @@ -135,7 +135,7 @@ static void lsExit() static void nbEnter() { - LOG_INFO("Enter state: NB\n"); + LOG_DEBUG("Enter state: NB\n"); screen->setOn(false); setBluetoothEnable(false); @@ -150,7 +150,7 @@ static void darkEnter() static void serialEnter() { - LOG_INFO("Enter state: SERIAL\n"); + LOG_DEBUG("Enter state: SERIAL\n"); setBluetoothEnable(false); screen->setOn(true); screen->print("Serial connected\n"); @@ -163,7 +163,7 @@ static void serialExit() static void powerEnter() { - LOG_INFO("Enter state: POWER\n"); + LOG_DEBUG("Enter state: POWER\n"); if (!isPowered()) { // If we got here, we are in the wrong state - we should be in powered, let that state ahndle things LOG_INFO("Loss of power in Powered\n"); @@ -198,7 +198,7 @@ static void powerExit() static void onEnter() { - LOG_INFO("Enter state: ON\n"); + LOG_DEBUG("Enter state: ON\n"); screen->setOn(true); setBluetoothEnable(true); } @@ -218,7 +218,7 @@ static void screenPress() static void bootEnter() { - LOG_INFO("Enter state: BOOT\n"); + LOG_DEBUG("Enter state: BOOT\n"); } State stateSHUTDOWN(shutdownEnter, NULL, NULL, "SHUTDOWN"); diff --git a/src/RedirectablePrint.cpp b/src/RedirectablePrint.cpp index 39ea76c00..0e8e1c798 100644 --- a/src/RedirectablePrint.cpp +++ b/src/RedirectablePrint.cpp @@ -62,6 +62,9 @@ size_t RedirectablePrint::vprintf(const char *format, va_list arg) size_t RedirectablePrint::log(const char *logLevel, const char *format, ...) { + if (moduleConfig.serial.override_console_serial_port && strcmp(logLevel, "DEBUG") == 0) { + return 0; + } size_t r = 0; if (!inDebugPrint) { diff --git a/src/SerialConsole.cpp b/src/SerialConsole.cpp index 91b4e2826..e827dcf3b 100644 --- a/src/SerialConsole.cpp +++ b/src/SerialConsole.cpp @@ -31,7 +31,7 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), con // setDestination(&noopPrint); for testing, try turning off 'all' debug output and see what leaks Port.begin(SERIAL_BAUD); -#if defined(ARCH_NRF52) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) +#if defined(ARCH_NRF52) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARCH_RP2040) time_t timeout = millis(); while (!Port) { if ((millis() - timeout) < 5000) { diff --git a/src/airtime.cpp b/src/airtime.cpp index 7be4c5b0d..2702ee2bf 100644 --- a/src/airtime.cpp +++ b/src/airtime.cpp @@ -6,20 +6,22 @@ AirTime *airTime = NULL; // Don't read out of this directly. Use the helper functions. +uint32_t air_period_tx[PERIODS_TO_LOG]; +uint32_t air_period_rx[PERIODS_TO_LOG]; + void AirTime::logAirtime(reportTypes reportType, uint32_t airtime_ms) { if (reportType == TX_LOG) { LOG_DEBUG("AirTime - Packet transmitted : %ums\n", airtime_ms); this->airtimes.periodTX[0] = this->airtimes.periodTX[0] + airtime_ms; - myNodeInfo.air_period_tx[0] = myNodeInfo.air_period_tx[0] + airtime_ms; + air_period_tx[0] = air_period_tx[0] + airtime_ms; this->utilizationTX[this->getPeriodUtilHour()] = this->utilizationTX[this->getPeriodUtilHour()] + airtime_ms; - } else if (reportType == RX_LOG) { LOG_DEBUG("AirTime - Packet received : %ums\n", airtime_ms); this->airtimes.periodRX[0] = this->airtimes.periodRX[0] + airtime_ms; - myNodeInfo.air_period_rx[0] = myNodeInfo.air_period_rx[0] + airtime_ms; + air_period_rx[0] = air_period_rx[0] + airtime_ms; } else if (reportType == RX_ALL_LOG) { LOG_DEBUG("AirTime - Packet received (noise?) : %ums\n", airtime_ms); this->airtimes.periodRX_ALL[0] = this->airtimes.periodRX_ALL[0] + airtime_ms; @@ -55,16 +57,16 @@ void AirTime::airtimeRotatePeriod() this->airtimes.periodRX[i + 1] = this->airtimes.periodRX[i]; this->airtimes.periodRX_ALL[i + 1] = this->airtimes.periodRX_ALL[i]; - myNodeInfo.air_period_tx[i + 1] = this->airtimes.periodTX[i]; - myNodeInfo.air_period_rx[i + 1] = this->airtimes.periodRX[i]; + air_period_tx[i + 1] = this->airtimes.periodTX[i]; + air_period_rx[i + 1] = this->airtimes.periodRX[i]; } this->airtimes.periodTX[0] = 0; this->airtimes.periodRX[0] = 0; this->airtimes.periodRX_ALL[0] = 0; - myNodeInfo.air_period_tx[0] = 0; - myNodeInfo.air_period_rx[0] = 0; + air_period_tx[0] = 0; + air_period_rx[0] = 0; this->airtimes.lastPeriodIndex = this->currentPeriodIndex(); } @@ -179,18 +181,17 @@ int32_t AirTime::runOnce() } // Init airtime windows to all 0 - for (int i = 0; i < myNodeInfo.air_period_rx_count; i++) { + for (int i = 0; i < PERIODS_TO_LOG; i++) { this->airtimes.periodTX[i] = 0; this->airtimes.periodRX[i] = 0; this->airtimes.periodRX_ALL[i] = 0; - // myNodeInfo.air_period_tx[i] = 0; - // myNodeInfo.air_period_rx[i] = 0; + // air_period_tx[i] = 0; + // air_period_rx[i] = 0; } firstTime = false; lastUtilPeriod = utilPeriod; - } else { this->airtimeRotatePeriod(); @@ -206,12 +207,6 @@ int32_t AirTime::runOnce() this->utilizationTX[utilPeriodTX] = 0; } - - // Update channel_utilization every second. - myNodeInfo.channel_utilization = airTime->channelUtilizationPercent(); - - // Update channel_utilization every second. - myNodeInfo.air_util_tx = airTime->utilizationTXPercent(); } /* LOG_DEBUG("utilPeriodTX %d TX Airtime %3.2f%\n", utilPeriodTX, airTime->utilizationTXPercent()); @@ -223,4 +218,4 @@ int32_t AirTime::runOnce() LOG_DEBUG("\n"); */ return (1000 * 1); -} +} \ No newline at end of file diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index b7f16734f..7afb03ee2 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -291,7 +291,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port) TwoWire *ScanI2CTwoWire::fetchI2CBus(ScanI2C::DeviceAddress address) const { - if (address.port == ScanI2C::I2CPort::WIRE1) { + if (address.port == ScanI2C::I2CPort::WIRE) { return &Wire; } else { #ifdef I2C_SDA1 diff --git a/src/error.h b/src/error.h index fc0707cd6..d16ee6595 100644 --- a/src/error.h +++ b/src/error.h @@ -9,4 +9,4 @@ /// Record an error that should be reported via analytics void recordCriticalError(meshtastic_CriticalErrorCode code = meshtastic_CriticalErrorCode_UNSPECIFIED, uint32_t address = 0, - const char *filename = NULL); + const char *filename = NULL); \ No newline at end of file diff --git a/src/freertosinc.h b/src/freertosinc.h index c5dfddc8e..166054241 100644 --- a/src/freertosinc.h +++ b/src/freertosinc.h @@ -12,7 +12,7 @@ #include #endif -#if defined(ARDUINO_NRF52_ADAFRUIT) +#if defined(ARDUINO_NRF52_ADAFRUIT) || defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_RP2040) #define HAS_FREE_RTOS #include @@ -44,4 +44,4 @@ typedef uint32_t BaseType_t; enum eNotifyAction { eNoAction, eSetValueWithoutOverwrite, eSetValueWithOverwrite }; -#endif +#endif \ No newline at end of file diff --git a/src/gps/NMEAWPL.cpp b/src/gps/NMEAWPL.cpp index ac11d78f8..9eff4d00e 100644 --- a/src/gps/NMEAWPL.cpp +++ b/src/gps/NMEAWPL.cpp @@ -18,10 +18,11 @@ * ------------------------------------------- */ -uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const char *name) +uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_PositionLite &pos, const char *name, bool isCaltopoMode) { GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude); - uint32_t len = snprintf(buf, bufsz, "$GNWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", geoCoord.getDMSLatDeg(), + char type = isCaltopoMode ? 'P' : 'N'; + uint32_t len = snprintf(buf, bufsz, "$G%cWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", type, geoCoord.getDMSLatDeg(), (abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6, geoCoord.getDMSLatCP(), geoCoord.getDMSLonDeg(), (abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6, geoCoord.getDMSLonCP(), name); @@ -33,6 +34,21 @@ uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const return len; } +uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const char *name, bool isCaltopoMode) +{ + GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude); + char type = isCaltopoMode ? 'P' : 'N'; + uint32_t len = snprintf(buf, bufsz, "$G%cWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", type, geoCoord.getDMSLatDeg(), + (abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6, geoCoord.getDMSLatCP(), + geoCoord.getDMSLonDeg(), (abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6, + geoCoord.getDMSLonCP(), name); + uint32_t chk = 0; + for (uint32_t i = 1; i < len; i++) { + chk ^= buf[i]; + } + len += snprintf(buf + len, bufsz - len, "*%02X\r\n", chk); + return len; +} /* ------------------------------------------- * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 * | | | | | | | | | | | | | | | diff --git a/src/gps/NMEAWPL.h b/src/gps/NMEAWPL.h index a9f00cb14..5821624c6 100644 --- a/src/gps/NMEAWPL.h +++ b/src/gps/NMEAWPL.h @@ -3,5 +3,6 @@ #include "main.h" #include -uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const char *name); -uint32_t printGGA(char *buf, size_t bufsz, const meshtastic_Position &pos); +uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const char *name, bool isCaltopoMode = false); +uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_PositionLite &pos, const char *name, bool isCaltopoMode = false); +uint32_t printGGA(char *buf, size_t bufsz, const meshtastic_Position &pos); \ No newline at end of file diff --git a/src/graphics/RAKled.h b/src/graphics/RAKled.h new file mode 100644 index 000000000..06e2a717f --- /dev/null +++ b/src/graphics/RAKled.h @@ -0,0 +1,7 @@ +#include "main.h" + +#ifdef RAK4630 +#include +extern NCP5623 rgb; + +#endif \ No newline at end of file diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 072a9d14d..f2c5da4e2 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -27,6 +27,7 @@ along with this program. If not, see . #include "GPS.h" #include "MeshService.h" #include "NodeDB.h" +#include "error.h" #include "gps/GeoCoord.h" #include "gps/RTC.h" #include "graphics/images.h" @@ -352,7 +353,7 @@ static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *sta display->setFont(FONT_MEDIUM); char tempBuf[24]; - snprintf(tempBuf, sizeof(tempBuf), "Critical fault #%d", myNodeInfo.error_code); + snprintf(tempBuf, sizeof(tempBuf), "Critical fault #%d", error_code); display->drawString(0 + x, 0 + y, tempBuf); display->setTextAlignment(TEXT_ALIGN_LEFT); display->setFont(FONT_SMALL); @@ -372,7 +373,7 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state static char tempBuf[237]; meshtastic_MeshPacket &mp = devicestate.rx_text_message; - meshtastic_NodeInfo *node = nodeDB.getNode(getFrom(&mp)); + meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp)); // LOG_DEBUG("drawing text message from 0x%x: %s\n", mp.from, // mp.decoded.variant.data.decoded.bytes); @@ -410,7 +411,7 @@ static void drawWaypointFrame(OLEDDisplay *display, OLEDDisplayUiState *state, i static char tempBuf[237]; meshtastic_MeshPacket &mp = devicestate.rx_waypoint; - meshtastic_NodeInfo *node = nodeDB.getNode(getFrom(&mp)); + meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp)); display->setTextAlignment(TEXT_ALIGN_LEFT); display->setFont(FONT_SMALL); @@ -711,13 +712,6 @@ static float estimatedHeading(double lat, double lon) return b; } -/// Sometimes we will have Position objects that only have a time, so check for -/// valid lat/lon -static bool hasPosition(meshtastic_NodeInfo *n) -{ - return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0); -} - static uint16_t getCompassDiam(OLEDDisplay *display) { uint16_t diam = 0; @@ -799,16 +793,16 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ if (state->currentFrame != prevFrame) { prevFrame = state->currentFrame; - nodeIndex = (nodeIndex + 1) % nodeDB.getNumNodes(); - meshtastic_NodeInfo *n = nodeDB.getNodeByIndex(nodeIndex); + nodeIndex = (nodeIndex + 1) % nodeDB.getNumMeshNodes(); + meshtastic_NodeInfoLite *n = nodeDB.getMeshNodeByIndex(nodeIndex); if (n->num == nodeDB.getNodeNum()) { // Don't show our node, just skip to next - nodeIndex = (nodeIndex + 1) % nodeDB.getNumNodes(); - n = nodeDB.getNodeByIndex(nodeIndex); + nodeIndex = (nodeIndex + 1) % nodeDB.getNumMeshNodes(); + n = nodeDB.getMeshNodeByIndex(nodeIndex); } } - meshtastic_NodeInfo *node = nodeDB.getNodeByIndex(nodeIndex); + meshtastic_NodeInfoLite *node = nodeDB.getMeshNodeByIndex(nodeIndex); display->setFont(FONT_SMALL); @@ -842,7 +836,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ static char distStr[20]; strncpy(distStr, "? km", sizeof(distStr)); // might not have location data - meshtastic_NodeInfo *ourNode = nodeDB.getNode(nodeDB.getNodeNum()); + meshtastic_NodeInfoLite *ourNode = nodeDB.getMeshNode(nodeDB.getNodeNum()); const char *fields[] = {username, distStr, signalStr, lastStr, NULL}; int16_t compassX = 0, compassY = 0; @@ -856,15 +850,15 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ } bool hasNodeHeading = false; - if (ourNode && hasPosition(ourNode)) { - meshtastic_Position &op = ourNode->position; + if (ourNode && hasValidPosition(ourNode)) { + meshtastic_PositionLite &op = ourNode->position; float myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i)); drawCompassNorth(display, compassX, compassY, myHeading); - if (hasPosition(node)) { + if (hasValidPosition(node)) { // display direction toward node hasNodeHeading = true; - meshtastic_Position &p = node->position; + meshtastic_PositionLite &p = node->position; float d = GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i)); @@ -892,7 +886,8 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ if (!hasNodeHeading) { // direction to node is unknown so display question mark // Debug info for gps lock errors - // LOG_DEBUG("ourNode %d, ourPos %d, theirPos %d\n", !!ourNode, ourNode && hasPosition(ourNode), hasPosition(node)); + // LOG_DEBUG("ourNode %d, ourPos %d, theirPos %d\n", !!ourNode, ourNode && hasValidPosition(ourNode), + // hasValidPosition(node)); display->drawString(compassX - FONT_HEIGHT_SMALL / 4, compassY - FONT_HEIGHT_SMALL / 2, "?"); } display->drawCircle(compassX, compassY, getCompassDiam(display) / 2); @@ -1245,9 +1240,9 @@ void Screen::setFrames() #endif // We don't show the node info our our node (if we have it yet - we should) - size_t numnodes = nodeDB.getNumNodes(); - if (numnodes > 0) - numnodes--; + size_t numMeshNodes = nodeDB.getNumMeshNodes(); + if (numMeshNodes > 0) + numMeshNodes--; size_t numframes = 0; @@ -1264,7 +1259,7 @@ void Screen::setFrames() LOG_DEBUG("Added modules. numframes: %d\n", numframes); // If we have a critical fault, show it first - if (myNodeInfo.error_code) + if (error_code) normalFrames[numframes++] = drawCriticalFaultFrame; // If we have a text message - show it next, unless it's a phone message and we aren't using any special modules @@ -1278,7 +1273,7 @@ void Screen::setFrames() // then all the nodes // We only show a few nodes in our scrolling list - because meshes with many nodes would have too many screens - size_t numToShow = min(numnodes, 4U); + size_t numToShow = min(numMeshNodes, 4U); for (size_t i = 0; i < numToShow; i++) normalFrames[numframes++] = drawNodeInfo; @@ -1855,4 +1850,4 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event) } // namespace graphics #else graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {} -#endif // HAS_SCREEN +#endif // HAS_SCREEN \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 19ed56662..c867930d0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,6 +19,7 @@ #include "detect/ScanI2CTwoWire.h" #include "detect/axpDebug.h" #include "detect/einkScan.h" +#include "graphics/RAKled.h" #include "graphics/Screen.h" #include "main.h" #include "mesh/generated/meshtastic/config.pb.h" @@ -59,6 +60,9 @@ NRF52Bluetooth *nrf52Bluetooth; #include "SX1262Interface.h" #include "SX1268Interface.h" #include "SX1280Interface.h" +#ifdef ARCH_STM32WL +#include "STM32WLE5JCInterface.h" +#endif #if !HAS_RADIO && defined(ARCH_PORTDUINO) #include "platform/portduino/SimRadio.h" #endif @@ -68,7 +72,7 @@ NRF52Bluetooth *nrf52Bluetooth; #endif #include "PowerFSMThread.h" -#if !defined(ARCH_PORTDUINO) +#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) #include "AccelerometerThread.h" #endif @@ -260,6 +264,12 @@ void setup() // We need to enable 3.3V periphery in order to scan it pinMode(PIN_3V3_EN, OUTPUT); digitalWrite(PIN_3V3_EN, HIGH); + +#ifndef USE_EINK + // RAK-12039 set pin for Air quality sensor + pinMode(AQ_SET_PIN, OUTPUT); + digitalWrite(AQ_SET_PIN, HIGH); +#endif #endif // Currently only the tbeam has a PMU @@ -347,10 +357,20 @@ void setup() * nodeTelemetrySensorsMap singleton. This wraps that logic in a temporary scope to declare the temporary field * "found". */ + // Only one supported RGB LED currently rgb_found = i2cScanner->find(ScanI2C::DeviceType::NCP5623); -#if !defined(ARCH_PORTDUINO) +// Start the RGB LED at 50% +#ifdef RAK4630 + if (rgb_found.type == ScanI2C::NCP5623) { + rgb.begin(); + rgb.setCurrent(10); + rgb.setColor(128, 128, 128); + } +#endif + +#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) auto acc_info = i2cScanner->firstAccelerometer(); accelerometer_found = acc_info.type != ScanI2C::DeviceType::NONE ? acc_info.address : accelerometer_found; LOG_DEBUG("acc_info = %i\n", acc_info.type); @@ -439,7 +459,7 @@ void setup() screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // keep dimension of 128x64 #endif -#if !defined(ARCH_PORTDUINO) +#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) if (acc_info.type != ScanI2C::DeviceType::NONE) { accelerometerThread = new AccelerometerThread(acc_info.type); } @@ -447,7 +467,21 @@ void setup() // Init our SPI controller (must be before screen and lora) initSPI(); -#ifndef ARCH_ESP32 +#ifdef ARCH_RP2040 +#ifdef HW_SPI1_DEVICE + SPI1.setSCK(RF95_SCK); + SPI1.setTX(RF95_MOSI); + SPI1.setRX(RF95_MISO); + pinMode(RF95_NSS, OUTPUT); + digitalWrite(RF95_NSS, HIGH); + SPI1.begin(false); +#else // HW_SPI1_DEVICE + SPI.setSCK(RF95_SCK); + SPI.setTX(RF95_MOSI); + SPI.setRX(RF95_MISO); + SPI.begin(false); +#endif // HW_SPI1_DEVICE +#elif !defined(ARCH_ESP32) // ARCH_RP2040 SPI.begin(); #else // ESP32 @@ -509,11 +543,25 @@ void setup() digitalWrite(SX126X_ANT_SW, 1); #endif - // Init LockingHAL first, to use it for radio init - +#ifdef HW_SPI1_DEVICE + LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI1, spiSettings); +#else // HW_SPI1_DEVICE LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); +#endif // radio init MUST BE AFTER service.init, so we have our radio config settings (from nodedb init) +#if defined(USE_STM32WLx) + if (!rIf) { + rIf = new STM32WLE5JCInterface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY); + if (!rIf->init()) { + LOG_WARN("Failed to find STM32WL radio\n"); + delete rIf; + rIf = NULL; + } else { + LOG_INFO("STM32WL Radio init succeeded, using STM32WL radio\n"); + } + } +#endif #if !HAS_RADIO && defined(ARCH_PORTDUINO) if (!rIf) { @@ -635,12 +683,10 @@ void setup() else { router->addInterface(rIf); - // Calculate and save the bit rate to myNodeInfo - // TODO: This needs to be added what ever method changes the channel from the phone. - myNodeInfo.bitrate = - (float(meshtastic_Constants_DATA_PAYLOAD_LEN) / (float(rIf->getPacketTime(meshtastic_Constants_DATA_PAYLOAD_LEN)))) * - 1000; - LOG_DEBUG("myNodeInfo.bitrate = %f bytes / sec\n", myNodeInfo.bitrate); + // Log bit rate to debug output + LOG_DEBUG("LoRA bitrate = %f bytes / sec\n", (float(meshtastic_Constants_DATA_PAYLOAD_LEN) / + (float(rIf->getPacketTime(meshtastic_Constants_DATA_PAYLOAD_LEN)))) * + 1000); } // This must be _after_ service.init because we need our preferences loaded from flash to have proper timeout values @@ -661,7 +707,7 @@ bool runASAP; extern meshtastic_DeviceMetadata getDeviceMetadata() { meshtastic_DeviceMetadata deviceMetadata; - strncpy(deviceMetadata.firmware_version, myNodeInfo.firmware_version, 18); + strncpy(deviceMetadata.firmware_version, optstr(APP_VERSION), sizeof(deviceMetadata.firmware_version)); deviceMetadata.device_state_version = DEVICESTATE_CUR_VER; deviceMetadata.canShutdown = pmu_found || HAS_CPU_SHUTDOWN; deviceMetadata.hasBluetooth = HAS_BLUETOOTH; @@ -718,4 +764,4 @@ void loop() mainDelay.delay(delayMsec); } // if (didWake) LOG_DEBUG("wake!\n"); -} +} \ No newline at end of file diff --git a/src/main.h b/src/main.h index 0d23dd10c..93baec590 100644 --- a/src/main.h +++ b/src/main.h @@ -38,8 +38,6 @@ extern bool isUSBPowered; extern ATECCX08A atecc; #endif -extern uint8_t nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1]; - extern int TCPPort; // set by Portduino // Global Screen singleton. @@ -69,4 +67,4 @@ void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), clearBonds(); meshtastic_DeviceMetadata getDeviceMetadata(); // FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that -extern SPISettings spiSettings; +extern SPISettings spiSettings; \ No newline at end of file diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index d8861943e..171199277 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -21,6 +21,7 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) { if (wasSeenRecently(p)) { // Note: this will also add a recent packet record printPacket("Ignoring incoming msg, because we've already seen it", p); + Router::cancelSending(p->from, p->id); // cancel rebroadcast of this message *if* there was already one return true; } @@ -62,4 +63,4 @@ void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas } // handle the packet as normal Router::sniffReceived(p, c); -} +} \ No newline at end of file diff --git a/src/mesh/InterfacesTemplates.cpp b/src/mesh/InterfacesTemplates.cpp index 73b0bdfbc..c732829e9 100644 --- a/src/mesh/InterfacesTemplates.cpp +++ b/src/mesh/InterfacesTemplates.cpp @@ -10,6 +10,9 @@ template class SX126xInterface; template class SX126xInterface; template class SX126xInterface; template class SX128xInterface; +#ifdef ARCH_STM32WL +template class SX126xInterface; +#endif #if HAS_ETHERNET #include "api/ethServerAPI.h" diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index 3b9ae26d2..2ad46a6b7 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -9,6 +9,7 @@ #include "NodeDB.h" #include "PowerFSM.h" #include "RTC.h" +#include "TypeConversions.h" #include "main.h" #include "mesh-pb-constants.h" #include "modules/NodeInfoModule.h" @@ -76,7 +77,8 @@ int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp) powerFSM.trigger(EVENT_PACKET_FOR_PHONE); // Possibly keep the node from sleeping nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio - if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB.getNode(mp->from)->has_user && nodeInfoModule) { + if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB.getMeshNode(mp->from)->has_user && + nodeInfoModule) { LOG_INFO("Heard a node on channel %d we don't know, sending NodeInfo and asking for a response.\n", mp->channel); nodeInfoModule->sendOurNodeInfo(mp->from, true, mp->channel); } @@ -236,10 +238,11 @@ void MeshService::sendToMesh(meshtastic_MeshPacket *p, RxSource src, bool ccToPh void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies) { - meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); + meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum()); + assert(node); - if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) { + if (hasValidPosition(node)) { if (positionModule) { LOG_INFO("Sending position ping to 0x%x, wantReplies=%d, channel=%d\n", dest, wantReplies, node->channel); positionModule->sendOurPosition(dest, wantReplies, node->channel); @@ -266,9 +269,9 @@ void MeshService::sendToPhone(meshtastic_MeshPacket *p) fromNum++; } -meshtastic_NodeInfo *MeshService::refreshMyNodeInfo() +meshtastic_NodeInfoLite *MeshService::refreshLocalMeshNode() { - meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); + meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum()); assert(node); // We might not have a position yet for our local node, in that case, at least try to send the time @@ -277,7 +280,7 @@ meshtastic_NodeInfo *MeshService::refreshMyNodeInfo() node->has_position = true; } - meshtastic_Position &position = node->position; + meshtastic_PositionLite &position = node->position; // Update our local node info with our time (even if we don't decide to update anyone else) node->last_heard = @@ -293,7 +296,7 @@ meshtastic_NodeInfo *MeshService::refreshMyNodeInfo() int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus) { // Update our local node info with our position (even if we don't decide to update anyone else) - meshtastic_NodeInfo *node = refreshMyNodeInfo(); + meshtastic_NodeInfoLite *node = refreshLocalMeshNode(); meshtastic_Position pos = meshtastic_Position_init_default; if (newStatus->getHasLock()) { @@ -307,12 +310,12 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus) #endif if (config.position.fixed_position) { LOG_WARN("Using fixed position\n"); - pos = node->position; + pos = ConvertToPosition(node->position); } } // Finally add a fresh timestamp and battery level reading - // I KNOW this is redundant with refreshMyNodeInfo() above, but these are + // I KNOW this is redundant with refreshLocalMeshNode() above, but these are // inexpensive nonblocking calls and can be refactored in due course pos.time = getValidTime(RTCQualityGPS); @@ -329,4 +332,4 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus) bool MeshService::isToPhoneQueueEmpty() { return toPhoneQueue.isEmpty(); -} +} \ No newline at end of file diff --git a/src/mesh/MeshService.h b/src/mesh/MeshService.h index 4314ea362..d14db7139 100644 --- a/src/mesh/MeshService.h +++ b/src/mesh/MeshService.h @@ -98,7 +98,7 @@ class MeshService bool cancelSending(PacketId id); /// Pull the latest power and time info into my nodeinfo - meshtastic_NodeInfo *refreshMyNodeInfo(); + meshtastic_NodeInfoLite *refreshLocalMeshNode(); /// Send a packet to the phone void sendToPhone(meshtastic_MeshPacket *p); @@ -118,4 +118,4 @@ class MeshService ErrorCode sendQueueStatusToPhone(const meshtastic_QueueStatus &qs, ErrorCode res, uint32_t mesh_packet_id); }; -extern MeshService service; +extern MeshService service; \ No newline at end of file diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index feabd5029..b3841afe2 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -11,6 +11,7 @@ #include "PowerFSM.h" #include "RTC.h" #include "Router.h" +#include "TypeConversions.h" #include "error.h" #include "main.h" #include "mesh-pb-constants.h" @@ -55,10 +56,18 @@ extern void getMacAddr(uint8_t *dmac); * we use !macaddr (no colons). */ meshtastic_User &owner = devicestate.owner; +meshtastic_Position localPosition = meshtastic_Position_init_default; +meshtastic_CriticalErrorCode error_code = + meshtastic_CriticalErrorCode_NONE; // For the error code, only show values from this boot (discard value from flash) +uint32_t error_address = 0; static uint8_t ourMacAddr[6]; -NodeDB::NodeDB() : nodes(devicestate.node_db), numNodes(&devicestate.node_db_count) {} +NodeDB::NodeDB() + : nodes(devicestate.node_db), numNodes(&devicestate.node_db_count), meshNodes(devicestate.node_db_lite), + numMeshNodes(&devicestate.node_db_lite_count) +{ +} /** * Most (but not always) of the time we want to treat packets 'from' the local phone (where from == 0), as if they originated on @@ -258,6 +267,9 @@ void NodeDB::resetNodes() { devicestate.node_db_count = 0; memset(devicestate.node_db, 0, sizeof(devicestate.node_db)); + + devicestate.node_db_lite_count = 0; + memset(devicestate.node_db_lite, 0, sizeof(devicestate.node_db_lite)); saveDeviceStateToDisk(); } @@ -272,17 +284,12 @@ void NodeDB::installDefaultDeviceState() devicestate.has_my_node = true; devicestate.has_owner = true; devicestate.node_db_count = 0; + devicestate.node_db_lite_count = 0; devicestate.version = DEVICESTATE_CUR_VER; devicestate.receive_queue_count = 0; // Not yet implemented FIXME - // default to no GPS, until one has been found by probing - myNodeInfo.has_gps = false; - myNodeInfo.message_timeout_msec = FLOOD_EXPIRE_TIME; generatePacketId(); // FIXME - ugly way to init current_packet_id; - // Init our blank owner info to reasonable defaults - getMacAddr(ourMacAddr); - // Set default owner name pickNewNodeNum(); // based on macaddr now snprintf(owner.long_name, sizeof(owner.long_name), "Meshtastic %02x%02x", ourMacAddr[4], ourMacAddr[5]); @@ -303,28 +310,34 @@ void NodeDB::init() int saveWhat = 0; - myNodeInfo.max_channels = MAX_NUM_CHANNELS; // tell others the max # of channels we can understand - - myNodeInfo.error_code = - meshtastic_CriticalErrorCode_NONE; // For the error code, only show values from this boot (discard value from flash) - myNodeInfo.error_address = 0; - // likewise - we always want the app requirements to come from the running appload - myNodeInfo.min_app_version = 20300; // format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20 - + myNodeInfo.min_app_version = 20300; // format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20 + myNodeInfo.max_channels = MAX_NUM_CHANNELS; // tell others the max # of channels we can understand // Note! We do this after loading saved settings, so that if somehow an invalid nodenum was stored in preferences we won't // keep using that nodenum forever. Crummy guess at our nodenum (but we will check against the nodedb to avoid conflicts) + strncpy(myNodeInfo.firmware_version, optstr(APP_VERSION), sizeof(myNodeInfo.firmware_version)); pickNewNodeNum(); // Set our board type so we can share it with others owner.hw_model = HW_VENDOR; // Include our owner in the node db under our nodenum - meshtastic_NodeInfo *info = getOrCreateNode(getNodeNum()); + meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getNodeNum()); info->user = owner; info->has_user = true; - strncpy(myNodeInfo.firmware_version, optstr(APP_VERSION), sizeof(myNodeInfo.firmware_version)); + if (*numNodes > 0) { + LOG_DEBUG("Legacy NodeDB detected... Migrating to NodeDBLite\n"); + uint32_t readIndex = 0; + const meshtastic_NodeInfo *oldNodeInfo = nodeDB.readNextNodeInfo(readIndex); + while (oldNodeInfo != NULL) { + migrateToNodeInfoLite(oldNodeInfo); + oldNodeInfo = nodeDB.readNextNodeInfo(readIndex); + } + LOG_DEBUG("Migration complete! Clearing out legacy NodeDB...\n"); + devicestate.node_db_count = 0; + memset(devicestate.node_db, 0, sizeof(devicestate.node_db)); + } #ifdef ARCH_ESP32 Preferences preferences; @@ -332,11 +345,6 @@ void NodeDB::init() myNodeInfo.reboot_count = preferences.getUInt("rebootCounter", 0); preferences.end(); LOG_DEBUG("Number of Device Reboots: %d\n", myNodeInfo.reboot_count); - - /* The ESP32 has a wifi radio. This will need to be modified at some point so - * the test isn't so simplistic. - */ - myNodeInfo.has_wifi = true; #endif resetRadioConfig(); // If bogus settings got saved, then fix them @@ -367,17 +375,19 @@ void NodeDB::pickNewNodeNum() { NodeNum r = myNodeInfo.my_node_num; - // If we don't have a nodenum at app - pick an initial nodenum based on the macaddr - if (r == 0) - r = (ourMacAddr[2] << 24) | (ourMacAddr[3] << 16) | (ourMacAddr[4] << 8) | ourMacAddr[5]; + getMacAddr(ourMacAddr); // Make sure ourMacAddr is set + + // Pick an initial nodenum based on the macaddr + r = (ourMacAddr[2] << 24) | (ourMacAddr[3] << 16) | (ourMacAddr[4] << 8) | ourMacAddr[5]; if (r == NODENUM_BROADCAST || r < NUM_RESERVED) r = NUM_RESERVED; // don't pick a reserved node number - meshtastic_NodeInfo *found; - while ((found = getNode(r)) && memcmp(found->user.macaddr, owner.macaddr, sizeof(owner.macaddr))) { + meshtastic_NodeInfoLite *found; + while ((found = getMeshNode(r)) && memcmp(found->user.macaddr, owner.macaddr, sizeof(owner.macaddr))) { + // FIXME: input for random() is int, so NODENUM_BROADCAST becomes -1 NodeNum n = random(NUM_RESERVED, NODENUM_BROADCAST); // try a new random choice - LOG_DEBUG("NOTE! Our desired nodenum 0x%x is in use, so trying for 0x%x\n", r, n); + LOG_WARN("NOTE! Our desired nodenum 0x%x is in use, so trying for 0x%x\n", r, n); r = n; } @@ -584,16 +594,24 @@ void NodeDB::saveToDisk(int saveWhat) } } -const meshtastic_NodeInfo *NodeDB::readNextInfo() +const meshtastic_NodeInfo *NodeDB::readNextNodeInfo(uint32_t &readIndex) { - if (readPointer < *numNodes) - return &nodes[readPointer++]; + if (readIndex < *numNodes) + return &nodes[readIndex++]; + else + return NULL; +} + +const meshtastic_NodeInfoLite *NodeDB::readNextMeshNode(uint32_t &readIndex) +{ + if (readIndex < *numMeshNodes) + return &meshNodes[readIndex++]; else return NULL; } /// Given a node, return how many seconds in the past (vs now) that we last heard from it -uint32_t sinceLastSeen(const meshtastic_NodeInfo *n) +uint32_t sinceLastSeen(const meshtastic_NodeInfoLite *n) { uint32_t now = getTime(); @@ -617,13 +635,13 @@ uint32_t sinceReceived(const meshtastic_MeshPacket *p) #define NUM_ONLINE_SECS (60 * 60 * 2) // 2 hrs to consider someone offline -size_t NodeDB::getNumOnlineNodes() +size_t NodeDB::getNumOnlineMeshNodes() { size_t numseen = 0; // FIXME this implementation is kinda expensive - for (int i = 0; i < *numNodes; i++) - if (sinceLastSeen(&nodes[i]) < NUM_ONLINE_SECS) + for (int i = 0; i < *numMeshNodes; i++) + if (sinceLastSeen(&meshNodes[i]) < NUM_ONLINE_SECS) numseen++; return numseen; @@ -635,7 +653,7 @@ size_t NodeDB::getNumOnlineNodes() */ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSource src) { - meshtastic_NodeInfo *info = getOrCreateNode(nodeId); + meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId); if (!info) { return; } @@ -644,7 +662,9 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou // Local packet, fully authoritative LOG_INFO("updatePosition LOCAL pos@%x, time=%u, latI=%d, lonI=%d, alt=%d\n", p.timestamp, p.time, p.latitude_i, p.longitude_i, p.altitude); - info->position = p; + + info->position = ConvertToPositionLite(p); + localPosition = p; } else if ((p.time > 0) && !p.latitude_i && !p.longitude_i && !p.timestamp && !p.location_source) { // FIXME SPECIAL TIME SETTING PACKET FROM EUD TO RADIO // (stop-gap fix for issue #900) @@ -662,7 +682,7 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou uint32_t tmp_time = info->position.time; // Next, update atomically - info->position = p; + info->position = ConvertToPositionLite(p); // Last, restore any fields that may have been overwritten if (!info->position.time) @@ -678,7 +698,7 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou */ void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxSource src) { - meshtastic_NodeInfo *info = getOrCreateNode(nodeId); + meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId); // Environment metrics should never go to NodeDb but we'll safegaurd anyway if (!info || t.which_variant != meshtastic_Telemetry_device_metrics_tag) { return; @@ -700,7 +720,7 @@ void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxS */ bool NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p) { - meshtastic_NodeInfo *info = getOrCreateNode(nodeId); + meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId); if (!info) { return false; } @@ -733,7 +753,7 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp) if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.from) { LOG_DEBUG("Update DB node 0x%x, rx_time=%u, channel=%d\n", mp.from, mp.rx_time, mp.channel); - meshtastic_NodeInfo *info = getOrCreateNode(getFrom(&mp)); + meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getFrom(&mp)); if (!info) { return; } @@ -750,9 +770,9 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp) } } -uint8_t NodeDB::getNodeChannel(NodeNum n) +uint8_t NodeDB::getMeshNodeChannel(NodeNum n) { - meshtastic_NodeInfo *info = getNode(n); + meshtastic_NodeInfoLite *info = getMeshNode(n); if (!info) { return 0; // defaults to PRIMARY } @@ -761,7 +781,7 @@ uint8_t NodeDB::getNodeChannel(NodeNum n) /// Find a node in our DB, return null for missing /// NOTE: This function might be called from an ISR -meshtastic_NodeInfo *NodeDB::getNode(NodeNum n) +meshtastic_NodeInfo *NodeDB::getNodeInfo(NodeNum n) { for (int i = 0; i < *numNodes; i++) if (nodes[i].num == n) @@ -770,38 +790,100 @@ meshtastic_NodeInfo *NodeDB::getNode(NodeNum n) return NULL; } -/// Find a node in our DB, create an empty NodeInfo if missing -meshtastic_NodeInfo *NodeDB::getOrCreateNode(NodeNum n) +/// Find a node in our DB, return null for missing +/// NOTE: This function might be called from an ISR +meshtastic_NodeInfoLite *NodeDB::getMeshNode(NodeNum n) { - meshtastic_NodeInfo *info = getNode(n); + for (int i = 0; i < *numMeshNodes; i++) + if (meshNodes[i].num == n) + return &meshNodes[i]; - if (!info) { - if ((*numNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfo_size * 3)) { - screen->print("warning: node_db full! erasing oldest entry\n"); + return NULL; +} + +/// Find a node in our DB, create an empty NodeInfo if missing +meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n) +{ + meshtastic_NodeInfoLite *lite = getMeshNode(n); + + if (!lite) { + if ((*numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfoLite_size * 3)) { + screen->print("warning: node_db_lite full! erasing oldest entry\n"); // look for oldest node and erase it uint32_t oldest = UINT32_MAX; int oldestIndex = -1; - for (int i = 0; i < *numNodes; i++) { - if (nodes[i].last_heard < oldest) { - oldest = nodes[i].last_heard; + for (int i = 0; i < *numMeshNodes; i++) { + if (meshNodes[i].last_heard < oldest) { + oldest = meshNodes[i].last_heard; oldestIndex = i; } } // Shove the remaining nodes down the chain - for (int i = oldestIndex; i < *numNodes - 1; i++) { - nodes[i] = nodes[i + 1]; + for (int i = oldestIndex; i < *numMeshNodes - 1; i++) { + meshNodes[i] = meshNodes[i + 1]; } - (*numNodes)--; + (*numMeshNodes)--; } // add the node at the end - info = &nodes[(*numNodes)++]; + lite = &meshNodes[(*numMeshNodes)++]; // everything is missing except the nodenum - memset(info, 0, sizeof(*info)); - info->num = n; + memset(lite, 0, sizeof(*lite)); + lite->num = n; } - return info; + return lite; +} + +void NodeDB::migrateToNodeInfoLite(const meshtastic_NodeInfo *node) +{ + meshtastic_NodeInfoLite *lite = getMeshNode(node->num); + + if (!lite) { + if ((*numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfoLite_size * 3)) { + screen->print("warning: node_db_lite full! erasing oldest entry\n"); + // look for oldest node and erase it + uint32_t oldest = UINT32_MAX; + int oldestIndex = -1; + for (int i = 0; i < *numMeshNodes; i++) { + if (meshNodes[i].last_heard < oldest) { + oldest = meshNodes[i].last_heard; + oldestIndex = i; + } + } + // Shove the remaining nodes down the chain + for (int i = oldestIndex; i < *numMeshNodes - 1; i++) { + meshNodes[i] = meshNodes[i + 1]; + } + (*numMeshNodes)--; + } + // add the node at the end + lite = &meshNodes[(*numMeshNodes)++]; + + // everything is missing except the nodenum + memset(lite, 0, sizeof(*lite)); + lite->num = node->num; + lite->snr = node->snr; + lite->last_heard = node->last_heard; + lite->channel = node->channel; + + if (node->has_position) { + lite->has_position = true; + lite->position.latitude_i = node->position.latitude_i; + lite->position.longitude_i = node->position.longitude_i; + lite->position.altitude = node->position.altitude; + lite->position.location_source = node->position.location_source; + lite->position.time = node->position.time; + } + if (node->has_user) { + lite->has_user = true; + lite->user = node->user; + } + if (node->has_device_metrics) { + lite->has_device_metrics = true; + lite->device_metrics = node->device_metrics; + } + } } /// Record an error that should be reported via analytics @@ -817,13 +899,12 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co } // Record error to DB - myNodeInfo.error_code = code; - myNodeInfo.error_address = address; - myNodeInfo.error_count++; + error_code = code; + error_address = address; // Currently portuino is mostly used for simulation. Make sue the user notices something really bad happend #ifdef ARCH_PORTDUINO LOG_ERROR("A critical failure occurred, portduino is exiting..."); exit(2); #endif -} +} \ No newline at end of file diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index 541b51f83..83d9e252f 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -7,6 +7,7 @@ #include "MeshTypes.h" #include "NodeStatus.h" #include "mesh-pb-constants.h" +#include "mesh/generated/meshtastic/mesh.pb.h" // For CriticalErrorCode /* DeviceState versions used to be defined in the .proto file but really only this function cares. So changed to a @@ -28,9 +29,10 @@ extern meshtastic_LocalConfig config; extern meshtastic_LocalModuleConfig moduleConfig; extern meshtastic_OEMStore oemStore; extern meshtastic_User &owner; +extern meshtastic_Position localPosition; /// Given a node, return how many seconds in the past (vs now) that we last heard from it -uint32_t sinceLastSeen(const meshtastic_NodeInfo *n); +uint32_t sinceLastSeen(const meshtastic_NodeInfoLite *n); /// Given a packet, return how many seconds in the past (vs now) it was received uint32_t sinceReceived(const meshtastic_MeshPacket *p); @@ -46,11 +48,12 @@ class NodeDB meshtastic_NodeInfo *nodes; pb_size_t *numNodes; - uint32_t readPointer = 0; + meshtastic_NodeInfoLite *meshNodes; + pb_size_t *numMeshNodes; public: bool updateGUI = false; // we think the gui should definitely be redrawn, screen will clear this once handled - meshtastic_NodeInfo *updateGUIforNode = NULL; // if currently showing this node, we think you should update the GUI + meshtastic_NodeInfoLite *updateGUIforNode = NULL; // if currently showing this node, we think you should update the GUI Observable newStatus; /// don't do mesh based algoritm for node id assignment (initially) @@ -91,8 +94,6 @@ class NodeDB /// @return our node number NodeNum getNodeNum() { return myNodeInfo.my_node_num; } - size_t getNumNodes() { return *numNodes; } - /// if returns false, that means our node should send a DenyNodeNum response. If true, we think the number is okay for use // bool handleWantNodeNum(NodeNum n); @@ -104,29 +105,14 @@ class NodeDB their denial?) */ - /// Called from bluetooth when the user wants to start reading the node DB from scratch. - void resetReadPointer() { readPointer = 0; } - - /// Allow the bluetooth layer to read our next nodeinfo record, or NULL if done reading - const meshtastic_NodeInfo *readNextInfo(); - /// pick a provisional nodenum we hope no one is using void pickNewNodeNum(); // get channel channel index we heard a nodeNum on, defaults to 0 if not found - uint8_t getNodeChannel(NodeNum n); - - /// Find a node in our DB, return null for missing - meshtastic_NodeInfo *getNode(NodeNum n); - - meshtastic_NodeInfo *getNodeByIndex(size_t x) - { - assert(x < *numNodes); - return &nodes[x]; - } + uint8_t getMeshNodeChannel(NodeNum n); /// Return the number of nodes we've heard from recently (within the last 2 hrs?) - size_t getNumOnlineNodes(); + size_t getNumOnlineMeshNodes(); void initConfigIntervals(), initModuleConfigIntervals(), resetNodes(); @@ -137,15 +123,38 @@ class NodeDB void installRoleDefaults(meshtastic_Config_DeviceConfig_Role role); + const meshtastic_NodeInfoLite *readNextMeshNode(uint32_t &readIndex); + + meshtastic_NodeInfoLite *getMeshNodeByIndex(size_t x) + { + assert(x < *numMeshNodes); + return &meshNodes[x]; + } + + meshtastic_NodeInfoLite *getMeshNode(NodeNum n); + size_t getNumMeshNodes() { return *numMeshNodes; } + private: - /// Find a node in our DB, create an empty NodeInfo if missing - meshtastic_NodeInfo *getOrCreateNode(NodeNum n); + /// Find a node in our DB, create an empty NodeInfoLite if missing + meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n); + void migrateToNodeInfoLite(const meshtastic_NodeInfo *node); + /// Find a node in our DB, return null for missing + meshtastic_NodeInfo *getNodeInfo(NodeNum n); + /// Allow the bluetooth layer to read our next nodeinfo record, or NULL if done reading + const meshtastic_NodeInfo *readNextNodeInfo(uint32_t &readIndex); + size_t getNumNodes() { return *numNodes; } + + meshtastic_NodeInfo *getNodeByIndex(size_t x) + { + assert(x < *numNodes); + return &nodes[x]; + } /// Notify observers of changes to the DB void notifyObservers(bool forceUpdate = false) { // Notify observers of the current node state - const meshtastic::NodeStatus status = meshtastic::NodeStatus(getNumOnlineNodes(), getNumNodes(), forceUpdate); + const meshtastic::NodeStatus status = meshtastic::NodeStatus(getNumOnlineMeshNodes(), getNumMeshNodes(), forceUpdate); newStatus.notifyObservers(&status); } @@ -217,12 +226,30 @@ inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t d return defaultInterval * 1000; } +/// Sometimes we will have Position objects that only have a time, so check for +/// valid lat/lon +static inline bool hasValidPosition(const meshtastic_NodeInfo *n) +{ + return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0); +} +static inline bool hasValidPosition(const meshtastic_NodeInfoLite *n) +{ + return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0); +} + /** The current change # for radio settings. Starts at 0 on boot and any time the radio settings * might have changed is incremented. Allows others to detect they might now be on a new channel. */ extern uint32_t radioGeneration; +extern meshtastic_CriticalErrorCode error_code; + +/* + * A numeric error address (nonzero if available) + */ +extern uint32_t error_address; + #define Module_Config_size \ (ModuleConfig_CannedMessageConfig_size + ModuleConfig_ExternalNotificationConfig_size + ModuleConfig_MQTTConfig_size + \ ModuleConfig_RangeTestConfig_size + ModuleConfig_SerialConfig_size + ModuleConfig_StoreForwardConfig_size + \ - ModuleConfig_TelemetryConfig_size + ModuleConfig_size) + ModuleConfig_TelemetryConfig_size + ModuleConfig_size) \ No newline at end of file diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 559f7ed31..ebc886301 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -5,6 +5,7 @@ #include "NodeDB.h" #include "PowerFSM.h" #include "RadioInterface.h" +#include "TypeConversions.h" #include "configuration.h" #include "main.h" #include "xmodem.h" @@ -40,9 +41,8 @@ void PhoneAPI::handleStartConfig() state = STATE_SEND_MY_INFO; LOG_INFO("Starting API client config\n"); - nodeInfoForPhone = NULL; // Don't keep returning old nodeinfos - nodeDB.resetReadPointer(); // FIXME, this read pointer should be moved out of nodeDB and into this class - because - // this will break once we have multiple instances of PhoneAPI running independently + nodeInfoForPhone.num = 0; // Don't keep returning old nodeinfos + resetReadIndex(); } void PhoneAPI::close() @@ -144,25 +144,23 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) LOG_INFO("getFromRadio=STATE_SEND_MY_INFO\n"); // If the user has specified they don't want our node to share its location, make sure to tell the phone // app not to send locations on our behalf. - myNodeInfo.has_gps = gps && gps->isConnected(); // Update with latest GPS connect info fromRadioScratch.which_payload_variant = meshtastic_FromRadio_my_info_tag; fromRadioScratch.my_info = myNodeInfo; state = STATE_SEND_NODEINFO; - service.refreshMyNodeInfo(); // Update my NodeInfo because the client will be asking for it soon. + service.refreshLocalMeshNode(); // Update my NodeInfo because the client will be asking for it soon. break; case STATE_SEND_NODEINFO: { LOG_INFO("getFromRadio=STATE_SEND_NODEINFO\n"); - const meshtastic_NodeInfo *info = nodeInfoForPhone; - nodeInfoForPhone = NULL; // We just consumed a nodeinfo, will need a new one next time - if (info) { - LOG_INFO("Sending nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", info->num, info->last_heard, info->user.id, - info->user.long_name); + if (nodeInfoForPhone.num != 0) { + LOG_INFO("nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", nodeInfoForPhone.num, nodeInfoForPhone.last_heard, + nodeInfoForPhone.user.id, nodeInfoForPhone.user.long_name); fromRadioScratch.which_payload_variant = meshtastic_FromRadio_node_info_tag; - fromRadioScratch.node_info = *info; + fromRadioScratch.node_info = nodeInfoForPhone; // Stay in current state until done sending nodeinfos + nodeInfoForPhone.num = 0; // We just consumed a nodeinfo, will need a new one next time } else { LOG_INFO("Done sending nodeinfos\n"); state = STATE_SEND_CHANNELS; @@ -372,8 +370,12 @@ bool PhoneAPI::available() return true; case STATE_SEND_NODEINFO: - if (!nodeInfoForPhone) - nodeInfoForPhone = nodeDB.readNextInfo(); + if (nodeInfoForPhone.num == 0) { + auto nextNode = nodeDB.readNextMeshNode(readIndex); + if (nextNode) { + nodeInfoForPhone = ConvertToNodeInfo(nextNode); + } + } return true; // Always say we have something, because we might need to advance our state machine case STATE_SEND_PACKETS: { @@ -428,4 +430,4 @@ int PhoneAPI::onNotify(uint32_t newValue) } return 0; -} +} \ No newline at end of file diff --git a/src/mesh/PhoneAPI.h b/src/mesh/PhoneAPI.h index af8f1be26..8097ad34b 100644 --- a/src/mesh/PhoneAPI.h +++ b/src/mesh/PhoneAPI.h @@ -51,13 +51,16 @@ class PhoneAPI meshtastic_QueueStatus *queueStatusPacketForPhone = NULL; /// We temporarily keep the nodeInfo here between the call to available and getFromRadio - const meshtastic_NodeInfo *nodeInfoForPhone = NULL; + meshtastic_NodeInfo nodeInfoForPhone = meshtastic_NodeInfo_init_default; meshtastic_ToRadio toRadioScratch = { 0}; // this is a static scratch object, any data must be copied elsewhere before returning /// Use to ensure that clients don't get confused about old messages from the radio uint32_t config_nonce = 0; + uint32_t readIndex = 0; + + void resetReadIndex() { readIndex = 0; } public: PhoneAPI(); diff --git a/src/mesh/ProtobufModule.h b/src/mesh/ProtobufModule.h index bdfdea9ad..1771f4322 100644 --- a/src/mesh/ProtobufModule.h +++ b/src/mesh/ProtobufModule.h @@ -52,7 +52,7 @@ template class ProtobufModule : protected SinglePortModule */ const char *getSenderShortName(const meshtastic_MeshPacket &mp) { - auto node = nodeDB.getNode(getFrom(&mp)); + auto node = nodeDB.getMeshNode(getFrom(&mp)); const char *sender = (node) ? node->user.short_name : "???"; return sender; } @@ -86,4 +86,4 @@ template class ProtobufModule : protected SinglePortModule return handleReceivedProtobuf(mp, decoded) ? ProcessMessage::STOP : ProcessMessage::CONTINUE; } -}; +}; \ No newline at end of file diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 1eee86c8e..00af93e15 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -232,7 +232,8 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(float snr) delay = random(0, 2 * CWsize) * slotTimeMsec; LOG_DEBUG("rx_snr found in packet. As a router, setting tx delay:%d\n", delay); } else { - delay = random(0, pow(2, CWsize)) * slotTimeMsec; + // offset the maximum delay for routers: (2 * CWmax * slotTimeMsec) + delay = (2 * CWmax * slotTimeMsec) + random(0, pow(2, CWsize)) * slotTimeMsec; LOG_DEBUG("rx_snr found in packet. Setting tx delay:%d\n", delay); } diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index bce6b8a97..a74d41090 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -406,4 +406,4 @@ void RadioLibInterface::startSend(meshtastic_MeshPacket *txp) // bits enableInterrupt(isrTxLevel0); } -} +} \ No newline at end of file diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index 6635089e5..4634ca7ee 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -27,6 +27,19 @@ class LockingArduinoHal : public ArduinoHal void spiEndTransaction() override; }; +#if defined(USE_STM32WLx) +/** + * A wrapper for the RadioLib STM32WLx_Module class, that doesn't connect any pins as they are virtual + */ +class STM32WLx_ModuleWrapper : public STM32WLx_Module +{ + public: + STM32WLx_ModuleWrapper(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, + RADIOLIB_PIN_TYPE busy) + : STM32WLx_Module(){}; +}; +#endif + class RadioLibInterface : public RadioInterface, protected concurrency::NotifiedWorkerThread { /// Used as our notification from the ISR @@ -56,7 +69,11 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified float currentLimit = 100; // 100mA OCP - Should be acceptable for RFM95/SX127x chipset. +#if !defined(USE_STM32WLx) Module module; // The HW interface to the radio +#else + STM32WLx_ModuleWrapper module; +#endif /** * provides lowest common denominator RadioLib API diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 156b48209..6f020d739 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -178,7 +178,7 @@ ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src) } if (!p->channel) { // don't override if a channel was requested - p->channel = nodeDB.getNodeChannel(p->to); + p->channel = nodeDB.getMeshNodeChannel(p->to); LOG_DEBUG("localSend to channel %d\n", p->channel); } @@ -493,4 +493,4 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p) handleReceived(p); packetPool.release(p); -} +} \ No newline at end of file diff --git a/src/mesh/STM32WLE5JCInterface.cpp b/src/mesh/STM32WLE5JCInterface.cpp new file mode 100644 index 000000000..5b6fd0844 --- /dev/null +++ b/src/mesh/STM32WLE5JCInterface.cpp @@ -0,0 +1,45 @@ +#include "STM32WLE5JCInterface.h" +#include "configuration.h" +#include "error.h" + +#ifndef STM32WLx_MAX_POWER +#define STM32WLx_MAX_POWER 22 +#endif + +#ifdef ARCH_STM32WL + +STM32WLE5JCInterface::STM32WLE5JCInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, + RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy) + : SX126xInterface(hal, cs, irq, rst, busy) +{ +} + +bool STM32WLE5JCInterface::init() +{ + RadioLibInterface::init(); + + lora.setRfSwitchTable(rfswitch_pins, rfswitch_table); + + if (power == 0) + power = STM32WLx_MAX_POWER; + + if (power > STM32WLx_MAX_POWER) // This chip has lower power limits than some + power = STM32WLx_MAX_POWER; + + limitPower(); + + int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage); + + LOG_INFO("STM32WLx init result %d\n", res); + + LOG_INFO("Frequency set to %f\n", getFreq()); + LOG_INFO("Bandwidth set to %f\n", bw); + LOG_INFO("Power output set to %d\n", power); + + if (res == RADIOLIB_ERR_NONE) + startReceive(); // start receiving + + return res == RADIOLIB_ERR_NONE; +} + +#endif // ARCH_STM32WL diff --git a/src/mesh/STM32WLE5JCInterface.h b/src/mesh/STM32WLE5JCInterface.h new file mode 100644 index 000000000..73d53d92f --- /dev/null +++ b/src/mesh/STM32WLE5JCInterface.h @@ -0,0 +1,31 @@ +#pragma once + +#include "SX126xInterface.h" + +#ifdef ARCH_STM32WL + +/** + * Our adapter for STM32WLE5JC radios + */ +class STM32WLE5JCInterface : public SX126xInterface +{ + public: + STM32WLE5JCInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, + RADIOLIB_PIN_TYPE busy); + + virtual bool init() override; +}; + +// https://github.com/Seeed-Studio/LoRaWan-E5-Node/blob/main/Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_driver.c +static const float tcxoVoltage = 1.7; + +/* https://wiki.seeedstudio.com/LoRa-E5_STM32WLE5JC_Module/ + * Wio-E5 module ONLY transmits through RFO_HP + * Receive: PA4=1, PA5=0 + * Transmit(high output power, SMPS mode): PA4=0, PA5=1 */ +static const RADIOLIB_PIN_TYPE rfswitch_pins[3] = {PA4, PA5, RADIOLIB_NC}; + +static const Module::RfSwitchMode_t rfswitch_table[4] = { + {STM32WLx::MODE_IDLE, {LOW, LOW}}, {STM32WLx::MODE_RX, {HIGH, LOW}}, {STM32WLx::MODE_TX_HP, {LOW, HIGH}}, END_OF_MODE_TABLE}; + +#endif // ARCH_STM32WL \ No newline at end of file diff --git a/src/mesh/TypeConversions.h b/src/mesh/TypeConversions.h new file mode 100644 index 000000000..bfc87102b --- /dev/null +++ b/src/mesh/TypeConversions.h @@ -0,0 +1,54 @@ +#include "mesh/generated/meshtastic/deviceonly.pb.h" +#include "mesh/generated/meshtastic/mesh.pb.h" + +inline static meshtastic_NodeInfo ConvertToNodeInfo(const meshtastic_NodeInfoLite *lite) +{ + meshtastic_NodeInfo info = meshtastic_NodeInfo_init_default; + + info.num = lite->num; + info.snr = lite->snr; + info.last_heard = lite->last_heard; + info.channel = lite->channel; + + if (lite->has_position) { + info.has_position = true; + info.position.latitude_i = lite->position.latitude_i; + info.position.longitude_i = lite->position.longitude_i; + info.position.altitude = lite->position.altitude; + info.position.location_source = lite->position.location_source; + info.position.time = lite->position.time; + } + if (lite->has_user) { + info.has_user = true; + info.user = lite->user; + } + if (lite->has_device_metrics) { + info.has_device_metrics = true; + info.device_metrics = lite->device_metrics; + } + return info; +} + +inline static meshtastic_PositionLite ConvertToPositionLite(meshtastic_Position position) +{ + meshtastic_PositionLite lite = meshtastic_PositionLite_init_default; + lite.latitude_i = position.latitude_i; + lite.longitude_i = position.longitude_i; + lite.altitude = position.altitude; + lite.location_source = position.location_source; + lite.time = position.time; + + return lite; +} + +inline static meshtastic_Position ConvertToPosition(meshtastic_PositionLite lite) +{ + meshtastic_Position position = meshtastic_Position_init_default; + position.latitude_i = lite.latitude_i; + position.longitude_i = lite.longitude_i; + position.altitude = lite.altitude; + position.location_source = lite.location_source; + position.time = lite.time; + + return position; +} \ No newline at end of file diff --git a/src/mesh/TypedQueue.h b/src/mesh/TypedQueue.h index 721eec2c0..c08f9183b 100644 --- a/src/mesh/TypedQueue.h +++ b/src/mesh/TypedQueue.h @@ -74,7 +74,7 @@ template class TypedQueue concurrency::OSThread *reader = NULL; public: - TypedQueue(int maxElements) {} + explicit TypedQueue(int maxElements) {} int numFree() { return 1; } // Always claim 1 free, because we can grow to any size diff --git a/src/mesh/eth/ethClient.cpp b/src/mesh/eth/ethClient.cpp index 659de05f8..c60e35394 100644 --- a/src/mesh/eth/ethClient.cpp +++ b/src/mesh/eth/ethClient.cpp @@ -98,6 +98,11 @@ static int32_t reconnectETH() return 5000; // every 5 seconds } +static uint32_t bigToLittleEndian(uint32_t value) +{ + return ((value >> 24) & 0xFF) | ((value >> 8) & 0xFF00) | ((value << 8) & 0xFF0000) | ((value << 24) & 0xFF000000); +} + // Startup Ethernet bool initEthernet() { @@ -126,7 +131,15 @@ bool initEthernet() status = Ethernet.begin(mac); } else if (config.network.address_mode == meshtastic_Config_NetworkConfig_AddressMode_STATIC) { LOG_INFO("starting Ethernet Static\n"); - Ethernet.begin(mac, config.network.ipv4_config.ip, config.network.ipv4_config.dns, config.network.ipv4_config.subnet); + + IPAddress ip = IPAddress(bigToLittleEndian(config.network.ipv4_config.ip)); + IPAddress dns = IPAddress(bigToLittleEndian(config.network.ipv4_config.dns)); + IPAddress gateway = IPAddress(bigToLittleEndian(config.network.ipv4_config.gateway)); + IPAddress subnet = IPAddress(bigToLittleEndian(config.network.ipv4_config.subnet)); + + Ethernet.begin(mac, ip, dns, gateway, subnet); + + status = 1; } else { LOG_INFO("Ethernet Disabled\n"); return false; diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index b7c11a609..99314aef5 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -311,6 +311,8 @@ typedef struct _meshtastic_Config_PowerConfig { While in light sleep when we receive packets on the LoRa radio we will wake and handle them and stay awake in no BLE mode for this value 0 for default of 10 seconds */ uint32_t min_wake_secs; + /* I2C address of INA_2XX to use for reading device battery voltage */ + uint8_t device_battery_ina_address; } meshtastic_Config_PowerConfig; typedef struct _meshtastic_Config_NetworkConfig_IpV4Config { @@ -534,7 +536,7 @@ extern "C" { #define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}} #define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0} #define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""} #define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0} #define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0} @@ -543,7 +545,7 @@ extern "C" { #define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}} #define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0} #define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""} #define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0} #define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0} @@ -579,6 +581,7 @@ extern "C" { #define meshtastic_Config_PowerConfig_sds_secs_tag 6 #define meshtastic_Config_PowerConfig_ls_secs_tag 7 #define meshtastic_Config_PowerConfig_min_wake_secs_tag 8 +#define meshtastic_Config_PowerConfig_device_battery_ina_address_tag 9 #define meshtastic_Config_NetworkConfig_IpV4Config_ip_tag 1 #define meshtastic_Config_NetworkConfig_IpV4Config_gateway_tag 2 #define meshtastic_Config_NetworkConfig_IpV4Config_subnet_tag 3 @@ -682,7 +685,8 @@ X(a, STATIC, SINGULAR, UINT32, wait_bluetooth_secs, 4) \ X(a, STATIC, SINGULAR, UINT32, mesh_sds_timeout_secs, 5) \ X(a, STATIC, SINGULAR, UINT32, sds_secs, 6) \ X(a, STATIC, SINGULAR, UINT32, ls_secs, 7) \ -X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 8) +X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 8) \ +X(a, STATIC, SINGULAR, UINT32, device_battery_ina_address, 9) #define meshtastic_Config_PowerConfig_CALLBACK NULL #define meshtastic_Config_PowerConfig_DEFAULT NULL @@ -776,7 +780,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg; #define meshtastic_Config_NetworkConfig_IpV4Config_size 20 #define meshtastic_Config_NetworkConfig_size 195 #define meshtastic_Config_PositionConfig_size 54 -#define meshtastic_Config_PowerConfig_size 43 +#define meshtastic_Config_PowerConfig_size 46 #define meshtastic_Config_size 198 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.c b/src/mesh/generated/meshtastic/deviceonly.pb.c index e741d25de..82c3fc44c 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.c +++ b/src/mesh/generated/meshtastic/deviceonly.pb.c @@ -9,6 +9,12 @@ PB_BIND(meshtastic_DeviceState, meshtastic_DeviceState, 4) +PB_BIND(meshtastic_NodeInfoLite, meshtastic_NodeInfoLite, AUTO) + + +PB_BIND(meshtastic_PositionLite, meshtastic_PositionLite, AUTO) + + PB_BIND(meshtastic_ChannelFile, meshtastic_ChannelFile, 2) diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index cf64de5d2..48f93da5e 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -7,6 +7,7 @@ #include "meshtastic/channel.pb.h" #include "meshtastic/localonly.pb.h" #include "meshtastic/mesh.pb.h" +#include "meshtastic/telemetry.pb.h" #include "meshtastic/module_config.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -25,6 +26,47 @@ typedef enum _meshtastic_ScreenFonts { } meshtastic_ScreenFonts; /* Struct definitions */ +/* Position with static location information only for NodeDBLite */ +typedef struct _meshtastic_PositionLite { + /* The new preferred location encoding, multiply by 1e-7 to get degrees + in floating point */ + int32_t latitude_i; + /* TODO: REPLACE */ + int32_t longitude_i; + /* In meters above MSL (but see issue #359) */ + int32_t altitude; + /* This is usually not sent over the mesh (to save space), but it is sent + from the phone so that the local device can set its RTC If it is sent over + the mesh (because there are devices on the mesh without GPS), it will only + be sent by devices which has a hardware GPS clock. + seconds since 1970 */ + uint32_t time; + /* TODO: REPLACE */ + meshtastic_Position_LocSource location_source; +} meshtastic_PositionLite; + +typedef struct _meshtastic_NodeInfoLite { + /* The node number */ + uint32_t num; + /* The user info for this node */ + bool has_user; + meshtastic_User user; + /* This position data. Note: before 1.2.14 we would also store the last time we've heard from this node in position.time, that is no longer true. + Position.time now indicates the last time we received a POSITION from that node. */ + bool has_position; + meshtastic_PositionLite position; + /* Returns the Signal-to-noise ratio (SNR) of the last received message, + as measured by the receiver. Return SNR of the last received message in dB */ + float snr; + /* Set to indicate the last time we received a packet from this node */ + uint32_t last_heard; + /* The latest device metrics for the node. */ + bool has_device_metrics; + meshtastic_DeviceMetrics device_metrics; + /* local channel index we heard that node on. Only populated if its not the default channel. */ + uint8_t channel; +} meshtastic_NodeInfoLite; + /* The on-disk saved channels */ typedef struct _meshtastic_ChannelFile { /* The channels our node knows about */ @@ -82,7 +124,8 @@ typedef struct _meshtastic_DeviceState { /* My owner info */ bool has_owner; meshtastic_User owner; - /* TODO: REPLACE */ + /* Deprecated in 2.1.x + Old node_db. See NodeInfoLite node_db_lite */ pb_size_t node_db_count; meshtastic_NodeInfo node_db[80]; /* Received packets saved for delivery to the phone */ @@ -110,6 +153,9 @@ typedef struct _meshtastic_DeviceState { /* The mesh's nodes with their available gpio pins for RemoteHardware module */ pb_size_t node_remote_hardware_pins_count; meshtastic_NodeRemoteHardwarePin node_remote_hardware_pins[12]; + /* New lite version of NodeDB to decrease */ + pb_size_t node_db_lite_count; + meshtastic_NodeInfoLite node_db_lite[80]; } meshtastic_DeviceState; @@ -124,21 +170,40 @@ extern "C" { +#define meshtastic_PositionLite_location_source_ENUMTYPE meshtastic_Position_LocSource + + #define meshtastic_OEMStore_oem_font_ENUMTYPE meshtastic_ScreenFonts /* Initializer values for message structs */ -#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default}, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}} +#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default}, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}, 0, {meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default}} +#define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_User_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0} +#define meshtastic_PositionLite_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} #define meshtastic_ChannelFile_init_default {0, {meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default}, 0} #define meshtastic_OEMStore_init_default {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default} #define meshtastic_NodeRemoteHardwarePin_init_default {0, false, meshtastic_RemoteHardwarePin_init_default} -#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero}, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}} +#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero}, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}, 0, {meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero}} +#define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0} +#define meshtastic_PositionLite_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} #define meshtastic_ChannelFile_init_zero {0, {meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero}, 0} #define meshtastic_OEMStore_init_zero {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_zero, false, meshtastic_LocalModuleConfig_init_zero} #define meshtastic_NodeRemoteHardwarePin_init_zero {0, false, meshtastic_RemoteHardwarePin_init_zero} /* Field tags (for use in manual encoding/decoding) */ +#define meshtastic_PositionLite_latitude_i_tag 1 +#define meshtastic_PositionLite_longitude_i_tag 2 +#define meshtastic_PositionLite_altitude_tag 3 +#define meshtastic_PositionLite_time_tag 4 +#define meshtastic_PositionLite_location_source_tag 5 +#define meshtastic_NodeInfoLite_num_tag 1 +#define meshtastic_NodeInfoLite_user_tag 2 +#define meshtastic_NodeInfoLite_position_tag 3 +#define meshtastic_NodeInfoLite_snr_tag 4 +#define meshtastic_NodeInfoLite_last_heard_tag 5 +#define meshtastic_NodeInfoLite_device_metrics_tag 6 +#define meshtastic_NodeInfoLite_channel_tag 7 #define meshtastic_ChannelFile_channels_tag 1 #define meshtastic_ChannelFile_version_tag 2 #define meshtastic_OEMStore_oem_icon_width_tag 1 @@ -161,6 +226,7 @@ extern "C" { #define meshtastic_DeviceState_did_gps_reset_tag 11 #define meshtastic_DeviceState_rx_waypoint_tag 12 #define meshtastic_DeviceState_node_remote_hardware_pins_tag 13 +#define meshtastic_DeviceState_node_db_lite_tag 14 /* Struct field encoding specification for nanopb */ #define meshtastic_DeviceState_FIELDLIST(X, a) \ @@ -173,7 +239,8 @@ X(a, STATIC, SINGULAR, UINT32, version, 8) \ X(a, STATIC, SINGULAR, BOOL, no_save, 9) \ X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11) \ X(a, STATIC, OPTIONAL, MESSAGE, rx_waypoint, 12) \ -X(a, STATIC, REPEATED, MESSAGE, node_remote_hardware_pins, 13) +X(a, STATIC, REPEATED, MESSAGE, node_remote_hardware_pins, 13) \ +X(a, STATIC, REPEATED, MESSAGE, node_db_lite, 14) #define meshtastic_DeviceState_CALLBACK NULL #define meshtastic_DeviceState_DEFAULT NULL #define meshtastic_DeviceState_my_node_MSGTYPE meshtastic_MyNodeInfo @@ -183,6 +250,30 @@ X(a, STATIC, REPEATED, MESSAGE, node_remote_hardware_pins, 13) #define meshtastic_DeviceState_rx_text_message_MSGTYPE meshtastic_MeshPacket #define meshtastic_DeviceState_rx_waypoint_MSGTYPE meshtastic_MeshPacket #define meshtastic_DeviceState_node_remote_hardware_pins_MSGTYPE meshtastic_NodeRemoteHardwarePin +#define meshtastic_DeviceState_node_db_lite_MSGTYPE meshtastic_NodeInfoLite + +#define meshtastic_NodeInfoLite_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, num, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, user, 2) \ +X(a, STATIC, OPTIONAL, MESSAGE, position, 3) \ +X(a, STATIC, SINGULAR, FLOAT, snr, 4) \ +X(a, STATIC, SINGULAR, FIXED32, last_heard, 5) \ +X(a, STATIC, OPTIONAL, MESSAGE, device_metrics, 6) \ +X(a, STATIC, SINGULAR, UINT32, channel, 7) +#define meshtastic_NodeInfoLite_CALLBACK NULL +#define meshtastic_NodeInfoLite_DEFAULT NULL +#define meshtastic_NodeInfoLite_user_MSGTYPE meshtastic_User +#define meshtastic_NodeInfoLite_position_MSGTYPE meshtastic_PositionLite +#define meshtastic_NodeInfoLite_device_metrics_MSGTYPE meshtastic_DeviceMetrics + +#define meshtastic_PositionLite_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 1) \ +X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 2) \ +X(a, STATIC, SINGULAR, INT32, altitude, 3) \ +X(a, STATIC, SINGULAR, FIXED32, time, 4) \ +X(a, STATIC, SINGULAR, UENUM, location_source, 5) +#define meshtastic_PositionLite_CALLBACK NULL +#define meshtastic_PositionLite_DEFAULT NULL #define meshtastic_ChannelFile_FIELDLIST(X, a) \ X(a, STATIC, REPEATED, MESSAGE, channels, 1) \ @@ -213,21 +304,27 @@ X(a, STATIC, OPTIONAL, MESSAGE, pin, 2) #define meshtastic_NodeRemoteHardwarePin_pin_MSGTYPE meshtastic_RemoteHardwarePin extern const pb_msgdesc_t meshtastic_DeviceState_msg; +extern const pb_msgdesc_t meshtastic_NodeInfoLite_msg; +extern const pb_msgdesc_t meshtastic_PositionLite_msg; extern const pb_msgdesc_t meshtastic_ChannelFile_msg; extern const pb_msgdesc_t meshtastic_OEMStore_msg; extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define meshtastic_DeviceState_fields &meshtastic_DeviceState_msg +#define meshtastic_NodeInfoLite_fields &meshtastic_NodeInfoLite_msg +#define meshtastic_PositionLite_fields &meshtastic_PositionLite_msg #define meshtastic_ChannelFile_fields &meshtastic_ChannelFile_msg #define meshtastic_OEMStore_fields &meshtastic_OEMStore_msg #define meshtastic_NodeRemoteHardwarePin_fields &meshtastic_NodeRemoteHardwarePin_msg /* Maximum encoded size of messages (where known) */ #define meshtastic_ChannelFile_size 638 -#define meshtastic_DeviceState_size 22736 +#define meshtastic_DeviceState_size 35056 +#define meshtastic_NodeInfoLite_size 151 #define meshtastic_NodeRemoteHardwarePin_size 29 -#define meshtastic_OEMStore_size 3137 +#define meshtastic_OEMStore_size 3152 +#define meshtastic_PositionLite_size 28 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index 87638f32c..d70acc7fc 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -72,6 +72,9 @@ typedef struct _meshtastic_LocalModuleConfig { /* The part of the config that is specific to the Remote Hardware module */ bool has_remote_hardware; meshtastic_ModuleConfig_RemoteHardwareConfig remote_hardware; + /* The part of the config that is specific to the Neighbor Info module */ + bool has_neighbor_info; + meshtastic_ModuleConfig_NeighborInfoConfig neighbor_info; } meshtastic_LocalModuleConfig; @@ -81,9 +84,9 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_LocalConfig_init_default {false, meshtastic_Config_DeviceConfig_init_default, false, meshtastic_Config_PositionConfig_init_default, false, meshtastic_Config_PowerConfig_init_default, false, meshtastic_Config_NetworkConfig_init_default, false, meshtastic_Config_DisplayConfig_init_default, false, meshtastic_Config_LoRaConfig_init_default, false, meshtastic_Config_BluetoothConfig_init_default, 0} -#define meshtastic_LocalModuleConfig_init_default {false, meshtastic_ModuleConfig_MQTTConfig_init_default, false, meshtastic_ModuleConfig_SerialConfig_init_default, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_default, false, meshtastic_ModuleConfig_StoreForwardConfig_init_default, false, meshtastic_ModuleConfig_RangeTestConfig_init_default, false, meshtastic_ModuleConfig_TelemetryConfig_init_default, false, meshtastic_ModuleConfig_CannedMessageConfig_init_default, 0, false, meshtastic_ModuleConfig_AudioConfig_init_default, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_default} +#define meshtastic_LocalModuleConfig_init_default {false, meshtastic_ModuleConfig_MQTTConfig_init_default, false, meshtastic_ModuleConfig_SerialConfig_init_default, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_default, false, meshtastic_ModuleConfig_StoreForwardConfig_init_default, false, meshtastic_ModuleConfig_RangeTestConfig_init_default, false, meshtastic_ModuleConfig_TelemetryConfig_init_default, false, meshtastic_ModuleConfig_CannedMessageConfig_init_default, 0, false, meshtastic_ModuleConfig_AudioConfig_init_default, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_default, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_default} #define meshtastic_LocalConfig_init_zero {false, meshtastic_Config_DeviceConfig_init_zero, false, meshtastic_Config_PositionConfig_init_zero, false, meshtastic_Config_PowerConfig_init_zero, false, meshtastic_Config_NetworkConfig_init_zero, false, meshtastic_Config_DisplayConfig_init_zero, false, meshtastic_Config_LoRaConfig_init_zero, false, meshtastic_Config_BluetoothConfig_init_zero, 0} -#define meshtastic_LocalModuleConfig_init_zero {false, meshtastic_ModuleConfig_MQTTConfig_init_zero, false, meshtastic_ModuleConfig_SerialConfig_init_zero, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero, false, meshtastic_ModuleConfig_StoreForwardConfig_init_zero, false, meshtastic_ModuleConfig_RangeTestConfig_init_zero, false, meshtastic_ModuleConfig_TelemetryConfig_init_zero, false, meshtastic_ModuleConfig_CannedMessageConfig_init_zero, 0, false, meshtastic_ModuleConfig_AudioConfig_init_zero, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero} +#define meshtastic_LocalModuleConfig_init_zero {false, meshtastic_ModuleConfig_MQTTConfig_init_zero, false, meshtastic_ModuleConfig_SerialConfig_init_zero, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero, false, meshtastic_ModuleConfig_StoreForwardConfig_init_zero, false, meshtastic_ModuleConfig_RangeTestConfig_init_zero, false, meshtastic_ModuleConfig_TelemetryConfig_init_zero, false, meshtastic_ModuleConfig_CannedMessageConfig_init_zero, 0, false, meshtastic_ModuleConfig_AudioConfig_init_zero, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_zero} /* Field tags (for use in manual encoding/decoding) */ #define meshtastic_LocalConfig_device_tag 1 @@ -104,6 +107,7 @@ extern "C" { #define meshtastic_LocalModuleConfig_version_tag 8 #define meshtastic_LocalModuleConfig_audio_tag 9 #define meshtastic_LocalModuleConfig_remote_hardware_tag 10 +#define meshtastic_LocalModuleConfig_neighbor_info_tag 11 /* Struct field encoding specification for nanopb */ #define meshtastic_LocalConfig_FIELDLIST(X, a) \ @@ -135,7 +139,8 @@ 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, OPTIONAL, MESSAGE, audio, 9) \ -X(a, STATIC, OPTIONAL, MESSAGE, remote_hardware, 10) +X(a, STATIC, OPTIONAL, MESSAGE, remote_hardware, 10) \ +X(a, STATIC, OPTIONAL, MESSAGE, neighbor_info, 11) #define meshtastic_LocalModuleConfig_CALLBACK NULL #define meshtastic_LocalModuleConfig_DEFAULT NULL #define meshtastic_LocalModuleConfig_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig @@ -147,6 +152,7 @@ X(a, STATIC, OPTIONAL, MESSAGE, remote_hardware, 10) #define meshtastic_LocalModuleConfig_canned_message_MSGTYPE meshtastic_ModuleConfig_CannedMessageConfig #define meshtastic_LocalModuleConfig_audio_MSGTYPE meshtastic_ModuleConfig_AudioConfig #define meshtastic_LocalModuleConfig_remote_hardware_MSGTYPE meshtastic_ModuleConfig_RemoteHardwareConfig +#define meshtastic_LocalModuleConfig_neighbor_info_MSGTYPE meshtastic_ModuleConfig_NeighborInfoConfig extern const pb_msgdesc_t meshtastic_LocalConfig_msg; extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; @@ -156,8 +162,8 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; #define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg /* Maximum encoded size of messages (where known) */ -#define meshtastic_LocalConfig_size 458 -#define meshtastic_LocalModuleConfig_size 533 +#define meshtastic_LocalConfig_size 461 +#define meshtastic_LocalModuleConfig_size 545 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 98113c62b..0ed2f8e68 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -61,6 +61,8 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_NANO_G1_EXPLORER = 17, /* B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station */ meshtastic_HardwareModel_STATION_G1 = 25, + /* RAK11310 (RP2040 + SX1262) */ + meshtastic_HardwareModel_RAK11310 = 26, /* --------------------------------------------------------------------------- Less common/prototype boards listed here (needs one more byte over the air) --------------------------------------------------------------------------- */ @@ -93,6 +95,8 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_BETAFPV_2400_TX = 45, /* BetaFPV ExpressLRS "Nano" TX Module 900MHz with ESP32 CPU */ meshtastic_HardwareModel_BETAFPV_900_NANO_TX = 46, + /* Raspberry Pi Pico (W) with Waveshare SX1262 LoRa Node Module */ + meshtastic_HardwareModel_RPI_PICO = 47, /* ------------------------------------------------------------------------------------------------------------------------------------------ Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. ------------------------------------------------------------------------------------------------------------------------------------------ */ @@ -368,7 +372,8 @@ typedef struct _meshtastic_User { /* A VERY short name, ideally two characters. Suitable for a tiny OLED screen */ char short_name[5]; - /* This is the addr of the radio. + /* Deprecated in Meshtastic 2.1.x + This is the addr of the radio. Not populated by the phone, but added by the esp32 when broadcasting */ pb_byte_t macaddr[6]; /* TBEAM, HELTEC, etc... @@ -574,12 +579,15 @@ typedef struct _meshtastic_MyNodeInfo { /* Tells the phone what our node number is, default starting value is lowbyte of macaddr, but it will be fixed if that is already in use */ uint32_t my_node_num; - /* Note: This flag merely means we detected a hardware GPS in our node. + /* Deprecated in 2.1.x (Source from device_metadata) + Note: This flag merely means we detected a hardware GPS in our node. Not the same as UserPreferences.location_sharing */ bool has_gps; - /* The maximum number of 'software' channels that can be set on this node. */ + /* Deprecated in 2.1.x + The maximum number of 'software' channels that can be set on this node. */ uint32_t max_channels; - /* 0.0.5 etc... */ + /* Deprecated in 2.1.x (Source from device_metadata) + 0.0.5 etc... */ char firmware_version[18]; /* An error message we'd like to report back to the mothership through analytics. It indicates a serious bug occurred on the device, the device coped with it, @@ -596,9 +604,11 @@ typedef struct _meshtastic_MyNodeInfo { /* The total number of reboots this node has ever encountered (well - since the last time we discarded preferences) */ uint32_t reboot_count; - /* Calculated bitrate of the current channel (in Bytes Per Second) */ + /* Deprecated in 2.1.x + Calculated bitrate of the current channel (in Bytes Per Second) */ float bitrate; - /* How long before we consider a message abandoned and we can clear our + /* Deprecated in 2.1.x + How long before we consider a message abandoned and we can clear our caches of any messages in flight Normally quite large to handle the worst case message delivery time, 5 minutes. Formerly called FLOOD_EXPIRE_TIME in the device code */ @@ -606,17 +616,22 @@ typedef struct _meshtastic_MyNodeInfo { /* The minimum app version that can talk to this device. Phone/PC apps should compare this to their build number and if too low tell the user they must update their app */ uint32_t min_app_version; - /* 24 time windows of 1hr each with the airtime transmitted out of the device per hour. */ + /* Deprecated in 2.1.x (Only used on device to keep track of utilization) + 24 time windows of 1hr each with the airtime transmitted out of the device per hour. */ pb_size_t air_period_tx_count; uint32_t air_period_tx[8]; - /* 24 time windows of 1hr each with the airtime of valid packets for your mesh. */ + /* Deprecated in 2.1.x (Only used on device to keep track of utilization) + 24 time windows of 1hr each with the airtime of valid packets for your mesh. */ pb_size_t air_period_rx_count; uint32_t air_period_rx[8]; - /* Is the device wifi capable? */ + /* Deprecated in 2.1.x (Source from DeviceMetadata instead) + Is the device wifi capable? */ bool has_wifi; - /* Utilization for the current channel, including well formed TX, RX and malformed RX (aka noise). */ + /* Deprecated in 2.1.x (Source from DeviceMetrics telemetry payloads) + Utilization for the current channel, including well formed TX, RX and malformed RX (aka noise). */ float channel_utilization; - /* Percent of airtime for transmission used within the last hour. */ + /* Deprecated in 2.1.x (Source from DeviceMetrics telemetry payloads) + Percent of airtime for transmission used within the last hour. */ float air_util_tx; } meshtastic_MyNodeInfo; diff --git a/src/mesh/generated/meshtastic/module_config.pb.c b/src/mesh/generated/meshtastic/module_config.pb.c index 123a4fedf..9352feb17 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.c +++ b/src/mesh/generated/meshtastic/module_config.pb.c @@ -15,6 +15,9 @@ PB_BIND(meshtastic_ModuleConfig_MQTTConfig, meshtastic_ModuleConfig_MQTTConfig, PB_BIND(meshtastic_ModuleConfig_RemoteHardwareConfig, meshtastic_ModuleConfig_RemoteHardwareConfig, AUTO) +PB_BIND(meshtastic_ModuleConfig_NeighborInfoConfig, meshtastic_ModuleConfig_NeighborInfoConfig, AUTO) + + PB_BIND(meshtastic_ModuleConfig_AudioConfig, meshtastic_ModuleConfig_AudioConfig, AUTO) diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h index be1f33e2f..6273a89ae 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -58,7 +58,9 @@ typedef enum _meshtastic_ModuleConfig_SerialConfig_Serial_Mode { meshtastic_ModuleConfig_SerialConfig_Serial_Mode_SIMPLE = 1, meshtastic_ModuleConfig_SerialConfig_Serial_Mode_PROTO = 2, meshtastic_ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG = 3, - meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA = 4 + meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA = 4, + /* NMEA messages specifically tailored for CalTopo */ + meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO = 5 } meshtastic_ModuleConfig_SerialConfig_Serial_Mode; /* TODO: REPLACE */ @@ -112,6 +114,15 @@ typedef struct _meshtastic_ModuleConfig_MQTTConfig { char root[16]; } meshtastic_ModuleConfig_MQTTConfig; +/* NeighborInfoModule Config */ +typedef struct _meshtastic_ModuleConfig_NeighborInfoConfig { + /* Whether the Module is enabled */ + bool enabled; + /* Interval in seconds of how often we should try to send our + Neighbor Info to the mesh */ + uint32_t update_interval; +} meshtastic_ModuleConfig_NeighborInfoConfig; + /* Audio Config for codec2 voice */ typedef struct _meshtastic_ModuleConfig_AudioConfig { /* Whether Audio is enabled */ @@ -132,21 +143,24 @@ typedef struct _meshtastic_ModuleConfig_AudioConfig { /* Serial Config */ typedef struct _meshtastic_ModuleConfig_SerialConfig { - /* Preferences for the SerialModule - FIXME - Move this out of UserPreferences and into a section for module configuration. */ + /* Preferences for the SerialModule */ bool enabled; /* TODO: REPLACE */ bool echo; - /* TODO: REPLACE */ + /* RX pin (should match Arduino gpio pin number) */ uint32_t rxd; - /* TODO: REPLACE */ + /* TX pin (should match Arduino gpio pin number) */ uint32_t txd; - /* TODO: REPLACE */ + /* Serial baud rate */ meshtastic_ModuleConfig_SerialConfig_Serial_Baud baud; /* TODO: REPLACE */ uint32_t timeout; - /* TODO: REPLACE */ + /* Mode for serial module operation */ meshtastic_ModuleConfig_SerialConfig_Serial_Mode mode; + /* Overrides the platform's defacto Serial port instance to use with Serial module config settings + This is currently only usable in output modes like NMEA / CalTopo and may behave strangely or not work at all in other modes + Existing logging over the Serial Console will still be present */ + bool override_console_serial_port; } meshtastic_ModuleConfig_SerialConfig; /* External Notifications Config */ @@ -308,6 +322,8 @@ typedef struct _meshtastic_ModuleConfig { meshtastic_ModuleConfig_AudioConfig audio; /* TODO: REPLACE */ meshtastic_ModuleConfig_RemoteHardwareConfig remote_hardware; + /* TODO: REPLACE */ + meshtastic_ModuleConfig_NeighborInfoConfig neighbor_info; } payload_variant; } meshtastic_ModuleConfig; @@ -330,8 +346,8 @@ extern "C" { #define _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Baud)(meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600+1)) #define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN meshtastic_ModuleConfig_SerialConfig_Serial_Mode_DEFAULT -#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MAX meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA -#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Mode)(meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA+1)) +#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MAX meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO +#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Mode)(meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO+1)) #define _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE #define _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MAX meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK @@ -340,6 +356,7 @@ extern "C" { + #define meshtastic_ModuleConfig_AudioConfig_bitrate_ENUMTYPE meshtastic_ModuleConfig_AudioConfig_Audio_Baud #define meshtastic_ModuleConfig_SerialConfig_baud_ENUMTYPE meshtastic_ModuleConfig_SerialConfig_Serial_Baud @@ -360,8 +377,9 @@ extern "C" { #define meshtastic_ModuleConfig_init_default {0, {meshtastic_ModuleConfig_MQTTConfig_init_default}} #define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, ""} #define meshtastic_ModuleConfig_RemoteHardwareConfig_init_default {0, 0, 0, {meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default}} +#define meshtastic_ModuleConfig_NeighborInfoConfig_init_default {0, 0} #define meshtastic_ModuleConfig_AudioConfig_init_default {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0} -#define meshtastic_ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN} +#define meshtastic_ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0} #define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0} @@ -371,8 +389,9 @@ extern "C" { #define meshtastic_ModuleConfig_init_zero {0, {meshtastic_ModuleConfig_MQTTConfig_init_zero}} #define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, ""} #define meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero {0, 0, 0, {meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero}} +#define meshtastic_ModuleConfig_NeighborInfoConfig_init_zero {0, 0} #define meshtastic_ModuleConfig_AudioConfig_init_zero {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0} -#define meshtastic_ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN} +#define meshtastic_ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0} #define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0} @@ -389,6 +408,8 @@ extern "C" { #define meshtastic_ModuleConfig_MQTTConfig_json_enabled_tag 6 #define meshtastic_ModuleConfig_MQTTConfig_tls_enabled_tag 7 #define meshtastic_ModuleConfig_MQTTConfig_root_tag 8 +#define meshtastic_ModuleConfig_NeighborInfoConfig_enabled_tag 1 +#define meshtastic_ModuleConfig_NeighborInfoConfig_update_interval_tag 2 #define meshtastic_ModuleConfig_AudioConfig_codec2_enabled_tag 1 #define meshtastic_ModuleConfig_AudioConfig_ptt_pin_tag 2 #define meshtastic_ModuleConfig_AudioConfig_bitrate_tag 3 @@ -403,6 +424,7 @@ extern "C" { #define meshtastic_ModuleConfig_SerialConfig_baud_tag 5 #define meshtastic_ModuleConfig_SerialConfig_timeout_tag 6 #define meshtastic_ModuleConfig_SerialConfig_mode_tag 7 +#define meshtastic_ModuleConfig_SerialConfig_override_console_serial_port_tag 8 #define meshtastic_ModuleConfig_ExternalNotificationConfig_enabled_tag 1 #define meshtastic_ModuleConfig_ExternalNotificationConfig_output_ms_tag 2 #define meshtastic_ModuleConfig_ExternalNotificationConfig_output_tag 3 @@ -458,6 +480,7 @@ extern "C" { #define meshtastic_ModuleConfig_canned_message_tag 7 #define meshtastic_ModuleConfig_audio_tag 8 #define meshtastic_ModuleConfig_remote_hardware_tag 9 +#define meshtastic_ModuleConfig_neighbor_info_tag 10 /* Struct field encoding specification for nanopb */ #define meshtastic_ModuleConfig_FIELDLIST(X, a) \ @@ -469,7 +492,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,range_test,payload_variant.r 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,audio,payload_variant.audio), 8) \ -X(a, STATIC, ONEOF, MESSAGE, (payload_variant,remote_hardware,payload_variant.remote_hardware), 9) +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,remote_hardware,payload_variant.remote_hardware), 9) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,neighbor_info,payload_variant.neighbor_info), 10) #define meshtastic_ModuleConfig_CALLBACK NULL #define meshtastic_ModuleConfig_DEFAULT NULL #define meshtastic_ModuleConfig_payload_variant_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig @@ -481,6 +505,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,remote_hardware,payload_vari #define meshtastic_ModuleConfig_payload_variant_canned_message_MSGTYPE meshtastic_ModuleConfig_CannedMessageConfig #define meshtastic_ModuleConfig_payload_variant_audio_MSGTYPE meshtastic_ModuleConfig_AudioConfig #define meshtastic_ModuleConfig_payload_variant_remote_hardware_MSGTYPE meshtastic_ModuleConfig_RemoteHardwareConfig +#define meshtastic_ModuleConfig_payload_variant_neighbor_info_MSGTYPE meshtastic_ModuleConfig_NeighborInfoConfig #define meshtastic_ModuleConfig_MQTTConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, BOOL, enabled, 1) \ @@ -502,6 +527,12 @@ X(a, STATIC, REPEATED, MESSAGE, available_pins, 3) #define meshtastic_ModuleConfig_RemoteHardwareConfig_DEFAULT NULL #define meshtastic_ModuleConfig_RemoteHardwareConfig_available_pins_MSGTYPE meshtastic_RemoteHardwarePin +#define meshtastic_ModuleConfig_NeighborInfoConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, BOOL, enabled, 1) \ +X(a, STATIC, SINGULAR, UINT32, update_interval, 2) +#define meshtastic_ModuleConfig_NeighborInfoConfig_CALLBACK NULL +#define meshtastic_ModuleConfig_NeighborInfoConfig_DEFAULT NULL + #define meshtastic_ModuleConfig_AudioConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, BOOL, codec2_enabled, 1) \ X(a, STATIC, SINGULAR, UINT32, ptt_pin, 2) \ @@ -520,7 +551,8 @@ X(a, STATIC, SINGULAR, UINT32, rxd, 3) \ X(a, STATIC, SINGULAR, UINT32, txd, 4) \ X(a, STATIC, SINGULAR, UENUM, baud, 5) \ X(a, STATIC, SINGULAR, UINT32, timeout, 6) \ -X(a, STATIC, SINGULAR, UENUM, mode, 7) +X(a, STATIC, SINGULAR, UENUM, mode, 7) \ +X(a, STATIC, SINGULAR, BOOL, override_console_serial_port, 8) #define meshtastic_ModuleConfig_SerialConfig_CALLBACK NULL #define meshtastic_ModuleConfig_SerialConfig_DEFAULT NULL @@ -594,6 +626,7 @@ X(a, STATIC, SINGULAR, UENUM, type, 3) extern const pb_msgdesc_t meshtastic_ModuleConfig_msg; extern const pb_msgdesc_t meshtastic_ModuleConfig_MQTTConfig_msg; extern const pb_msgdesc_t meshtastic_ModuleConfig_RemoteHardwareConfig_msg; +extern const pb_msgdesc_t meshtastic_ModuleConfig_NeighborInfoConfig_msg; extern const pb_msgdesc_t meshtastic_ModuleConfig_AudioConfig_msg; extern const pb_msgdesc_t meshtastic_ModuleConfig_SerialConfig_msg; extern const pb_msgdesc_t meshtastic_ModuleConfig_ExternalNotificationConfig_msg; @@ -607,6 +640,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; #define meshtastic_ModuleConfig_fields &meshtastic_ModuleConfig_msg #define meshtastic_ModuleConfig_MQTTConfig_fields &meshtastic_ModuleConfig_MQTTConfig_msg #define meshtastic_ModuleConfig_RemoteHardwareConfig_fields &meshtastic_ModuleConfig_RemoteHardwareConfig_msg +#define meshtastic_ModuleConfig_NeighborInfoConfig_fields &meshtastic_ModuleConfig_NeighborInfoConfig_msg #define meshtastic_ModuleConfig_AudioConfig_fields &meshtastic_ModuleConfig_AudioConfig_msg #define meshtastic_ModuleConfig_SerialConfig_fields &meshtastic_ModuleConfig_SerialConfig_msg #define meshtastic_ModuleConfig_ExternalNotificationConfig_fields &meshtastic_ModuleConfig_ExternalNotificationConfig_msg @@ -621,9 +655,10 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; #define meshtastic_ModuleConfig_CannedMessageConfig_size 49 #define meshtastic_ModuleConfig_ExternalNotificationConfig_size 40 #define meshtastic_ModuleConfig_MQTTConfig_size 220 +#define meshtastic_ModuleConfig_NeighborInfoConfig_size 8 #define meshtastic_ModuleConfig_RangeTestConfig_size 10 #define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96 -#define meshtastic_ModuleConfig_SerialConfig_size 26 +#define meshtastic_ModuleConfig_SerialConfig_size 28 #define meshtastic_ModuleConfig_StoreForwardConfig_size 22 #define meshtastic_ModuleConfig_TelemetryConfig_size 26 #define meshtastic_ModuleConfig_size 223 diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 401e92f45..ae254e7f7 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -521,11 +521,23 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const void AdminModule::handleGetNodeRemoteHardwarePins(const meshtastic_MeshPacket &req) { - // We create the reply here meshtastic_AdminMessage r = meshtastic_AdminMessage_init_default; - memcpy(r.get_node_remote_hardware_pins_response.node_remote_hardware_pins, devicestate.node_remote_hardware_pins, - sizeof(devicestate.node_remote_hardware_pins)); r.which_payload_variant = meshtastic_AdminMessage_get_node_remote_hardware_pins_response_tag; + for (uint8_t i = 0; i < devicestate.node_remote_hardware_pins_count; i++) { + if (devicestate.node_remote_hardware_pins[i].node_num == 0 || !devicestate.node_remote_hardware_pins[i].has_pin) { + continue; + } + r.get_node_remote_hardware_pins_response.node_remote_hardware_pins[i] = devicestate.node_remote_hardware_pins[i]; + } + for (uint8_t i = 0; i < moduleConfig.remote_hardware.available_pins_count; i++) { + if (!moduleConfig.remote_hardware.available_pins[i].gpio_pin) { + continue; + } + meshtastic_NodeRemoteHardwarePin nodePin = meshtastic_NodeRemoteHardwarePin_init_default; + nodePin.node_num = nodeDB.getNodeNum(); + nodePin.pin = moduleConfig.remote_hardware.available_pins[i]; + r.get_node_remote_hardware_pins_response.node_remote_hardware_pins[i + 12] = nodePin; + } myReply = allocDataProtobuf(r); } @@ -541,9 +553,8 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r { meshtastic_AdminMessage r = meshtastic_AdminMessage_init_default; - meshtastic_DeviceConnectionStatus conn; + meshtastic_DeviceConnectionStatus conn = meshtastic_DeviceConnectionStatus_init_zero; - conn.wifi = {0}; #if HAS_WIFI conn.has_wifi = true; conn.wifi.has_status = true; @@ -559,11 +570,8 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r conn.wifi.status.is_mqtt_connected = mqtt && mqtt->connected(); conn.wifi.status.is_syslog_connected = false; // FIXME wire this up } -#else - conn.has_wifi = false; #endif - conn.ethernet = {0}; #if HAS_ETHERNET conn.has_ethernet = true; conn.ethernet.has_status = true; @@ -575,8 +583,6 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r } else { conn.ethernet.status.is_connected = false; } -#else - conn.has_ethernet = false; #endif #if HAS_BLUETOOTH diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index 5fba2b5de..bbd39f696 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -305,13 +305,14 @@ int32_t CannedMessageModule::runOnce() switch (this->payload) { case 0xb4: // left if (this->destSelect) { - size_t numNodes = nodeDB.getNumNodes(); + size_t numMeshNodes = nodeDB.getNumMeshNodes(); if (this->dest == NODENUM_BROADCAST) { this->dest = nodeDB.getNodeNum(); } - for (unsigned int i = 0; i < numNodes; i++) { - if (nodeDB.getNodeByIndex(i)->num == this->dest) { - this->dest = (i > 0) ? nodeDB.getNodeByIndex(i - 1)->num : nodeDB.getNodeByIndex(numNodes - 1)->num; + for (unsigned int i = 0; i < numMeshNodes; i++) { + if (nodeDB.getMeshNodeByIndex(i)->num == this->dest) { + this->dest = + (i > 0) ? nodeDB.getMeshNodeByIndex(i - 1)->num : nodeDB.getMeshNodeByIndex(numMeshNodes - 1)->num; break; } } @@ -326,13 +327,14 @@ int32_t CannedMessageModule::runOnce() break; case 0xb7: // right if (this->destSelect) { - size_t numNodes = nodeDB.getNumNodes(); + size_t numMeshNodes = nodeDB.getNumMeshNodes(); if (this->dest == NODENUM_BROADCAST) { this->dest = nodeDB.getNodeNum(); } - for (unsigned int i = 0; i < numNodes; i++) { - if (nodeDB.getNodeByIndex(i)->num == this->dest) { - this->dest = (i < numNodes - 1) ? nodeDB.getNodeByIndex(i + 1)->num : nodeDB.getNodeByIndex(0)->num; + for (unsigned int i = 0; i < numMeshNodes; i++) { + if (nodeDB.getMeshNodeByIndex(i)->num == this->dest) { + this->dest = + (i < numMeshNodes - 1) ? nodeDB.getMeshNodeByIndex(i + 1)->num : nodeDB.getMeshNodeByIndex(0)->num; break; } } @@ -409,7 +411,7 @@ const char *CannedMessageModule::getNodeName(NodeNum node) if (node == NODENUM_BROADCAST) { return "Broadcast"; } else { - meshtastic_NodeInfo *info = nodeDB.getNode(node); + meshtastic_NodeInfoLite *info = nodeDB.getMeshNode(node); if (info != NULL) { return info->user.long_name; } else { diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index 7dbf78a08..82701cdc0 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -11,7 +11,7 @@ #include "main.h" #ifdef RAK4630 -#include +#include NCP5623 rgb; uint8_t red = 0; diff --git a/src/modules/ExternalNotificationModule.h b/src/modules/ExternalNotificationModule.h index 7d4f54c2f..f8ec053dd 100644 --- a/src/modules/ExternalNotificationModule.h +++ b/src/modules/ExternalNotificationModule.h @@ -3,7 +3,7 @@ #include "SinglePortModule.h" #include "concurrency/OSThread.h" #include "configuration.h" -#ifndef ARCH_PORTDUINO +#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) #include #else // Noop class for portduino. diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp index 5d49a213e..61de2c265 100644 --- a/src/modules/Modules.cpp +++ b/src/modules/Modules.cpp @@ -22,12 +22,12 @@ #endif #ifdef ARCH_ESP32 #include "modules/esp32/AudioModule.h" -#include "modules/esp32/RangeTestModule.h" #include "modules/esp32/StoreForwardModule.h" #endif #if defined(ARCH_ESP32) || defined(ARCH_NRF52) #include "modules/ExternalNotificationModule.h" -#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2) +#include "modules/RangeTestModule.h" +#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(CONFIG_IDF_TARGET_ESP32S2) #include "modules/SerialModule.h" #endif #endif @@ -72,20 +72,18 @@ void setupModules() new AirQualityTelemetryModule(); } #endif -#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \ - !defined(CONFIG_IDF_TARGET_ESP32C3) +#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) new SerialModule(); #endif #ifdef ARCH_ESP32 // Only run on an esp32 based device. audioModule = new AudioModule(); - externalNotificationModule = new ExternalNotificationModule(); storeForwardModule = new StoreForwardModule(); - - new RangeTestModule(); -#elif defined(ARCH_NRF52) +#endif +#if defined(ARCH_ESP32) || defined(ARCH_NRF52) externalNotificationModule = new ExternalNotificationModule(); + new RangeTestModule(); #endif } else { adminModule = new AdminModule(); diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp index 89503d2b9..35457a23e 100644 --- a/src/modules/PositionModule.cpp +++ b/src/modules/PositionModule.cpp @@ -3,6 +3,7 @@ #include "NodeDB.h" #include "RTC.h" #include "Router.h" +#include "TypeConversions.h" #include "airtime.h" #include "configuration.h" #include "gps/GeoCoord.h" @@ -56,55 +57,57 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes meshtastic_MeshPacket *PositionModule::allocReply() { - meshtastic_NodeInfo *node = service.refreshMyNodeInfo(); // should guarantee there is now a position + meshtastic_NodeInfoLite *node = service.refreshLocalMeshNode(); // should guarantee there is now a position assert(node->has_position); - node->position.seq_number++; - // configuration of POSITION packet // consider making this a function argument? uint32_t pos_flags = config.position.position_flags; // Populate a Position struct with ONLY the requested fields meshtastic_Position p = meshtastic_Position_init_default; // Start with an empty structure + if (localPosition.latitude_i == 0 && localPosition.longitude_i == 0) { + localPosition = ConvertToPosition(node->position); + } + localPosition.seq_number++; // lat/lon are unconditionally included - IF AVAILABLE! - p.latitude_i = node->position.latitude_i; - p.longitude_i = node->position.longitude_i; - p.time = node->position.time; + p.latitude_i = localPosition.latitude_i; + p.longitude_i = localPosition.longitude_i; + p.time = localPosition.time; if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE) { if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE_MSL) - p.altitude = node->position.altitude; + p.altitude = localPosition.altitude; else - p.altitude_hae = node->position.altitude_hae; + p.altitude_hae = localPosition.altitude_hae; if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_GEOIDAL_SEPARATION) - p.altitude_geoidal_separation = node->position.altitude_geoidal_separation; + p.altitude_geoidal_separation = localPosition.altitude_geoidal_separation; } if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_DOP) { if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_HVDOP) { - p.HDOP = node->position.HDOP; - p.VDOP = node->position.VDOP; + p.HDOP = localPosition.HDOP; + p.VDOP = localPosition.VDOP; } else - p.PDOP = node->position.PDOP; + p.PDOP = localPosition.PDOP; } if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_SATINVIEW) - p.sats_in_view = node->position.sats_in_view; + p.sats_in_view = localPosition.sats_in_view; if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_TIMESTAMP) - p.timestamp = node->position.timestamp; + p.timestamp = localPosition.timestamp; if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_SEQ_NO) - p.seq_number = node->position.seq_number; + p.seq_number = localPosition.seq_number; if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_HEADING) - p.ground_track = node->position.ground_track; + p.ground_track = localPosition.ground_track; if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_SPEED) - p.ground_speed = node->position.ground_speed; + p.ground_speed = localPosition.ground_speed; // Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other // nodes shouldn't trust it anyways) Note: we allow a device with a local GPS to include the time, so that gpsless @@ -144,7 +147,7 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha int32_t PositionModule::runOnce() { - meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); + meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum()); // We limit our GPS broadcasts to a max rate uint32_t now = millis(); @@ -154,7 +157,7 @@ int32_t PositionModule::runOnce() if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) { // Only send packets if the channel is less than 40% utilized. if (airTime->isTxAllowedChannelUtil()) { - if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) { + if (hasValidPosition(node)) { lastGpsSend = now; lastGpsLatitude = node->position.latitude_i; @@ -164,16 +167,16 @@ int32_t PositionModule::runOnce() bool requestReplies = currentGeneration != radioGeneration; currentGeneration = radioGeneration; - LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", node->position.timestamp, requestReplies); + LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", localPosition.timestamp, requestReplies); sendOurPosition(NODENUM_BROADCAST, requestReplies); } } } else if (config.position.position_broadcast_smart_enabled) { // Only send packets if the channel is less than 25% utilized or we're a tracker. if (airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER)) { - meshtastic_NodeInfo *node2 = service.refreshMyNodeInfo(); // should guarantee there is now a position + meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position - if (node2->has_position && (node2->position.latitude_i != 0 || node2->position.longitude_i != 0)) { + if (hasValidPosition(node2)) { // The minimum distance to travel before we are able to send a new position packet. const uint32_t distanceTravelThreshold = config.position.broadcast_smart_minimum_distance > 0 ? config.position.broadcast_smart_minimum_distance : 100; @@ -193,7 +196,7 @@ int32_t PositionModule::runOnce() LOG_INFO("Sending smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, " "minTimeInterval=%ims)\n", - node2->position.timestamp, abs(distanceTraveledSinceLastSend), distanceTravelThreshold, + localPosition.timestamp, abs(distanceTraveledSinceLastSend), distanceTravelThreshold, msSinceLastSend, minimumTimeThreshold); sendOurPosition(NODENUM_BROADCAST, requestReplies); @@ -211,4 +214,4 @@ int32_t PositionModule::runOnce() } return 5000; // to save power only wake for our callback occasionally -} +} \ No newline at end of file diff --git a/src/modules/esp32/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp similarity index 97% rename from src/modules/esp32/RangeTestModule.cpp rename to src/modules/RangeTestModule.cpp index b3f03c04b..783fbd758 100644 --- a/src/modules/esp32/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -1,4 +1,5 @@ #include "RangeTestModule.h" +#include "FSCommon.h" #include "MeshService.h" #include "NodeDB.h" #include "PowerFSM.h" @@ -8,7 +9,6 @@ #include "configuration.h" #include "gps/GeoCoord.h" #include -#include /* As a sender, I can send packets every n seconds. These packets include an incremented PacketID. @@ -28,7 +28,7 @@ uint32_t packetSequence = 0; int32_t RangeTestModule::runOnce() { -#ifdef ARCH_ESP32 +#if defined(ARCH_ESP32) || defined(ARCH_NRF52) /* Uncomment the preferences below if you want to use the module @@ -60,7 +60,6 @@ int32_t RangeTestModule::runOnce() return disable(); // This thread does not need to run as a receiver } - } else { if (moduleConfig.range_test.sender) { @@ -122,7 +121,7 @@ void RangeTestModuleRadio::sendPayload(NodeNum dest, bool wantReplies) ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket &mp) { -#ifdef ARCH_ESP32 +#if defined(ARCH_ESP32) || defined(ARCH_NRF52) if (moduleConfig.range_test.enabled) { @@ -139,7 +138,7 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket } /* - NodeInfo *n = nodeDB.getNode(getFrom(&mp)); + NodeInfoLite *n = nodeDB.getMeshNode(getFrom(&mp)); LOG_DEBUG("-----------------------------------------\n"); LOG_DEBUG("p.payload.bytes \"%s\"\n", p.payload.bytes); @@ -153,7 +152,6 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket LOG_DEBUG("---- Node Information of Received Packet (mp.from):\n"); LOG_DEBUG("n->user.long_name %s\n", n->user.long_name); LOG_DEBUG("n->user.short_name %s\n", n->user.short_name); - LOG_DEBUG("n->user.macaddr %X\n", n->user.macaddr); LOG_DEBUG("n->has_position %d\n", n->has_position); LOG_DEBUG("n->position.latitude_i %d\n", n->position.latitude_i); LOG_DEBUG("n->position.longitude_i %d\n", n->position.longitude_i); @@ -165,7 +163,6 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket LOG_DEBUG("-----------------------------------------\n"); */ } - } else { LOG_INFO("Range Test Module Disabled\n"); } @@ -177,9 +174,10 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp) { +#ifdef ARCH_ESP32 auto &p = mp.decoded; - meshtastic_NodeInfo *n = nodeDB.getNode(getFrom(&mp)); + meshtastic_NodeInfoLite *n = nodeDB.getMeshNode(getFrom(&mp)); /* LOG_DEBUG("-----------------------------------------\n"); LOG_DEBUG("p.payload.bytes \"%s\"\n", p.payload.bytes); @@ -193,7 +191,6 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp) LOG_DEBUG("---- Node Information of Received Packet (mp.from):\n"); LOG_DEBUG("n->user.long_name %s\n", n->user.long_name); LOG_DEBUG("n->user.short_name %s\n", n->user.short_name); - LOG_DEBUG("n->user.macaddr %X\n", n->user.macaddr); LOG_DEBUG("n->has_position %d\n", n->has_position); LOG_DEBUG("n->position.latitude_i %d\n", n->position.latitude_i); LOG_DEBUG("n->position.longitude_i %d\n", n->position.longitude_i); @@ -284,6 +281,7 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp) fileToAppend.printf("\"%s\"\n", p.payload.bytes); fileToAppend.flush(); fileToAppend.close(); +#endif return 1; -} +} \ No newline at end of file diff --git a/src/modules/esp32/RangeTestModule.h b/src/modules/RangeTestModule.h similarity index 100% rename from src/modules/esp32/RangeTestModule.h rename to src/modules/RangeTestModule.h diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp index 35b83e6c6..af7ba1381 100644 --- a/src/modules/SerialModule.cpp +++ b/src/modules/SerialModule.cpp @@ -39,13 +39,12 @@ KNOWN PROBLEMS * Until the module is initilized by the startup sequence, the TX pin is in a floating state. Device connected to that pin may see this as "noise". - * Will not work on T-Echo and the Linux device targets. + * Will not work on Linux device targets. */ -#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \ - !defined(CONFIG_IDF_TARGET_ESP32C3) +#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) #define RX_BUFFER 128 #define TIMEOUT 250 @@ -58,19 +57,25 @@ SerialModule *serialModule; SerialModuleRadio *serialModuleRadio; +#ifdef TTGO_T_ECHO +SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("SerialModule") {} +static Print *serialPrint = &Serial; +#else SerialModule::SerialModule() : StreamAPI(&Serial2), concurrency::OSThread("SerialModule") {} +static Print *serialPrint = &Serial2; +#endif char serialBytes[meshtastic_Constants_DATA_PAYLOAD_LEN]; size_t serialPayloadSize; SerialModuleRadio::SerialModuleRadio() : MeshModule("SerialModuleRadio") { - switch (moduleConfig.serial.mode) { case meshtastic_ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG: ourPortNum = meshtastic_PortNum_TEXT_MESSAGE_APP; break; case meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA: + case meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO: ourPortNum = meshtastic_PortNum_POSITION_APP; break; default: @@ -95,89 +100,52 @@ int32_t SerialModule::runOnce() without having to configure it from the PythonAPI or WebUI. */ - // moduleConfig.serial.enabled = 1; + // moduleConfig.serial.enabled = true; // moduleConfig.serial.rxd = 35; // moduleConfig.serial.txd = 15; + // moduleConfig.serial.override_console_serial_port = true; + // moduleConfig.serial.mode = meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO; // moduleConfig.serial.timeout = 1000; // moduleConfig.serial.echo = 1; - if (moduleConfig.serial.enabled && moduleConfig.serial.rxd && moduleConfig.serial.txd) { + if (!moduleConfig.serial.enabled) + return disable(); + if (moduleConfig.serial.override_console_serial_port || (moduleConfig.serial.rxd && moduleConfig.serial.txd)) { if (firstTime) { - // Interface with the serial peripheral from in here. LOG_INFO("Initializing serial peripheral interface\n"); - uint32_t baud = 0; + uint32_t baud = getBaudRate(); - if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_DEFAULT) { - baud = 38400; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_110) { - baud = 110; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_300) { - baud = 300; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_600) { - baud = 600; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_1200) { - baud = 1200; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_2400) { - baud = 2400; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_4800) { - baud = 4800; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_9600) { - baud = 9600; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_19200) { - baud = 19200; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_38400) { - baud = 38400; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_57600) { - baud = 57600; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_115200) { - baud = 115200; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_230400) { - baud = 230400; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_460800) { - baud = 460800; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_576000) { - baud = 576000; - - } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600) { - baud = 921600; + if (moduleConfig.serial.override_console_serial_port) { + Serial.flush(); + serialPrint = &Serial; + // Give it a chance to flush out 💩 + delay(10); } - #ifdef ARCH_ESP32 - Serial2.setRxBufferSize(RX_BUFFER); if (moduleConfig.serial.rxd && moduleConfig.serial.txd) { + Serial2.setRxBufferSize(RX_BUFFER); Serial2.begin(baud, SERIAL_8N1, moduleConfig.serial.rxd, moduleConfig.serial.txd); + } else { + Serial.begin(baud); + Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT); + } +#elif !defined(TTGO_T_ECHO) + if (moduleConfig.serial.rxd && moduleConfig.serial.txd) { + Serial2.setPins(moduleConfig.serial.rxd, moduleConfig.serial.txd); + Serial2.begin(baud, SERIAL_8N1); + Serial2.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT); + } else { + Serial.begin(baud, SERIAL_8N1); + Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT); } #else - if (moduleConfig.serial.rxd && moduleConfig.serial.txd) - Serial2.setPins(moduleConfig.serial.rxd, moduleConfig.serial.txd); - - Serial2.begin(baud, SERIAL_8N1); - + Serial.begin(baud, SERIAL_8N1); + Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT); #endif - if (moduleConfig.serial.timeout) { - Serial2.setTimeout(moduleConfig.serial.timeout); // Number of MS to wait to set the timeout for the string. - } else { - Serial2.setTimeout(TIMEOUT); // Number of MS to wait to set the timeout for the string. - } - serialModuleRadio = new SerialModuleRadio(); firstTime = 0; @@ -186,26 +154,37 @@ int32_t SerialModule::runOnce() if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_PROTO) { emitRebooted(); } - } else { - if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_PROTO) { return runOncePart(); } else if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA) { // in NMEA mode send out GGA every 2 seconds, Don't read from Port if (millis() - lastNmeaTime > 2000) { lastNmeaTime = millis(); - printGGA(outbuf, sizeof(outbuf), nodeDB.getNode(myNodeInfo.my_node_num)->position); - Serial2.printf("%s", outbuf); + printGGA(outbuf, sizeof(outbuf), localPosition); + serialPrint->printf("%s", outbuf); } - } else { + } else if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO) { + if (millis() - lastNmeaTime > 10000) { + lastNmeaTime = millis(); + uint32_t readIndex = 0; + const meshtastic_NodeInfoLite *tempNodeInfo = nodeDB.readNextMeshNode(readIndex); + while (tempNodeInfo != NULL && tempNodeInfo->has_user && hasValidPosition(tempNodeInfo)) { + printWPL(outbuf, sizeof(outbuf), tempNodeInfo->position, tempNodeInfo->user.long_name, true); + serialPrint->printf("%s", outbuf); + tempNodeInfo = nodeDB.readNextMeshNode(readIndex); + } + } + } +#ifndef TTGO_T_ECHO + else { while (Serial2.available()) { serialPayloadSize = Serial2.readBytes(serialBytes, meshtastic_Constants_DATA_PAYLOAD_LEN); serialModuleRadio->sendPayload(); } } +#endif } - return (10); } else { return disable(); @@ -262,23 +241,23 @@ ProcessMessage SerialModuleRadio::handleReceived(const meshtastic_MeshPacket &mp if (lastRxID != mp.id) { lastRxID = mp.id; // LOG_DEBUG("* * Message came this device\n"); - // Serial2.println("* * Message came this device"); - Serial2.printf("%s", p.payload.bytes); + // serialPrint->println("* * Message came this device"); + serialPrint->printf("%s", p.payload.bytes); } } - } else { if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_DEFAULT || moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_SIMPLE) { - Serial2.printf("%s", p.payload.bytes); + serialPrint->printf("%s", p.payload.bytes); } else if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG) { - meshtastic_NodeInfo *node = nodeDB.getNode(getFrom(&mp)); + meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp)); String sender = (node && node->has_user) ? node->user.short_name : "???"; - Serial2.println(); - Serial2.printf("%s: %s", sender, p.payload.bytes); - Serial2.println(); - } else if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA) { + serialPrint->println(); + serialPrint->printf("%s: %s", sender, p.payload.bytes); + serialPrint->println(); + } else if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA || + moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO) { // Decode the Payload some more meshtastic_Position scratch; meshtastic_Position *decoded = NULL; @@ -288,12 +267,49 @@ ProcessMessage SerialModuleRadio::handleReceived(const meshtastic_MeshPacket &mp decoded = &scratch; } // send position packet as WPL to the serial port - printWPL(outbuf, sizeof(outbuf), *decoded, nodeDB.getNode(getFrom(&mp))->user.long_name); - Serial2.printf("%s", outbuf); + printWPL(outbuf, sizeof(outbuf), *decoded, nodeDB.getMeshNode(getFrom(&mp))->user.long_name, + moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO); + serialPrint->printf("%s", outbuf); } } } } return ProcessMessage::CONTINUE; // Let others look at this message also if they want } -#endif + +uint32_t SerialModule::getBaudRate() +{ + if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_110) { + return 110; + } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_300) { + return 300; + } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_600) { + return 600; + } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_1200) { + return 1200; + } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_2400) { + return 2400; + } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_4800) { + return 4800; + } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_9600) { + return 9600; + } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_19200) { + return 19200; + } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_38400) { + return 38400; + } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_57600) { + return 57600; + } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_115200) { + return 115200; + } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_230400) { + return 230400; + } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_460800) { + return 460800; + } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_576000) { + return 576000; + } else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600) { + return 921600; + } + return BAUD; +} +#endif \ No newline at end of file diff --git a/src/modules/SerialModule.h b/src/modules/SerialModule.h index cc696316d..562ccd42b 100644 --- a/src/modules/SerialModule.h +++ b/src/modules/SerialModule.h @@ -8,8 +8,7 @@ #include #include -#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \ - !defined(CONFIG_IDF_TARGET_ESP32C3) +#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) class SerialModule : public StreamAPI, private concurrency::OSThread { @@ -25,6 +24,9 @@ class SerialModule : public StreamAPI, private concurrency::OSThread /// Check the current underlying physical link to see if the client is currently connected virtual bool checkIsConnected() override; + + private: + uint32_t getBaudRate(); }; extern SerialModule *serialModule; diff --git a/src/modules/Telemetry/DeviceTelemetry.cpp b/src/modules/Telemetry/DeviceTelemetry.cpp index 696429aeb..4ef5a9a13 100644 --- a/src/modules/Telemetry/DeviceTelemetry.cpp +++ b/src/modules/Telemetry/DeviceTelemetry.cpp @@ -50,14 +50,14 @@ bool DeviceTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly) t.time = getTime(); t.which_variant = meshtastic_Telemetry_device_metrics_tag; - t.variant.device_metrics.air_util_tx = myNodeInfo.air_util_tx; + t.variant.device_metrics.air_util_tx = airTime->utilizationTXPercent(); if (powerStatus->getIsCharging()) { t.variant.device_metrics.battery_level = MAGIC_USB_BATTERY_LEVEL; } else { t.variant.device_metrics.battery_level = powerStatus->getBatteryChargePercent(); } - t.variant.device_metrics.channel_utilization = myNodeInfo.channel_utilization; + t.variant.device_metrics.channel_utilization = airTime->channelUtilizationPercent(); t.variant.device_metrics.voltage = powerStatus->getBatteryVoltageMv() / 1000.0; LOG_INFO("(Sending): air_util_tx=%f, channel_utilization=%f, battery_level=%i, voltage=%f\n", @@ -78,4 +78,4 @@ bool DeviceTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly) service.sendToMesh(p, RX_SRC_LOCAL, true); } return true; -} +} \ No newline at end of file diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index bf0ca6182..5cdc4bf4d 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -7,6 +7,7 @@ #include "Router.h" #include "configuration.h" #include "main.h" +#include "power.h" #include #include @@ -14,8 +15,6 @@ #include "Sensor/BME280Sensor.h" #include "Sensor/BME680Sensor.h" #include "Sensor/BMP280Sensor.h" -#include "Sensor/INA219Sensor.h" -#include "Sensor/INA260Sensor.h" #include "Sensor/LPS22HBSensor.h" #include "Sensor/MCP9808Sensor.h" #include "Sensor/SHT31Sensor.h" @@ -25,8 +24,6 @@ BMP280Sensor bmp280Sensor; BME280Sensor bme280Sensor; BME680Sensor bme680Sensor; MCP9808Sensor mcp9808Sensor; -INA260Sensor ina260Sensor; -INA219Sensor ina219Sensor; SHTC3Sensor shtc3Sensor; LPS22HBSensor lps22hbSensor; SHT31Sensor sht31Sensor; @@ -52,7 +49,7 @@ SHT31Sensor sht31Sensor; int32_t EnvironmentTelemetryModule::runOnce() { - int32_t result = INT32_MAX; + uint32_t result = UINT32_MAX; /* Uncomment the preferences below if you want to use the module without having to configure it from the PythonAPI or WebUI. @@ -83,23 +80,22 @@ int32_t EnvironmentTelemetryModule::runOnce() result = bme680Sensor.runOnce(); if (mcp9808Sensor.hasSensor()) result = mcp9808Sensor.runOnce(); - if (ina260Sensor.hasSensor()) - result = ina260Sensor.runOnce(); - if (ina219Sensor.hasSensor()) - result = ina219Sensor.runOnce(); if (shtc3Sensor.hasSensor()) result = shtc3Sensor.runOnce(); - if (lps22hbSensor.hasSensor()) { + if (lps22hbSensor.hasSensor()) result = lps22hbSensor.runOnce(); - } if (sht31Sensor.hasSensor()) result = sht31Sensor.runOnce(); } return result; } else { // if we somehow got to a second run of this module with measurement disabled, then just wait forever - if (!moduleConfig.telemetry.environment_measurement_enabled) - return result; + if (!moduleConfig.telemetry.environment_measurement_enabled) { + return disable(); + } else { + if (bme680Sensor.hasSensor()) + result = bme680Sensor.runTrigger(); + } uint32_t now = millis(); if (((lastSentToMesh == 0) || @@ -107,13 +103,15 @@ int32_t EnvironmentTelemetryModule::runOnce() airTime->isTxAllowedAirUtil()) { sendTelemetry(); lastSentToMesh = now; - } else if (service.isToPhoneQueueEmpty()) { + } else if (((lastSentToPhone == 0) || ((now - lastSentToPhone) >= sendToPhoneIntervalMs)) && + (service.isToPhoneQueueEmpty())) { // Just send to phone when it's not our time to send to mesh yet // Only send while queue is empty (phone assumed connected) sendTelemetry(NODENUM_BROADCAST, true); + lastSentToPhone = now; } } - return sendToPhoneIntervalMs; + return min(sendToPhoneIntervalMs, result); } bool EnvironmentTelemetryModule::wantUIFrame() @@ -205,6 +203,7 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPac bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly) { meshtastic_Telemetry m; + bool valid = false; m.time = getTime(); m.which_variant = meshtastic_Telemetry_environment_metrics_tag; @@ -216,50 +215,52 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly) m.variant.environment_metrics.voltage = 0; if (sht31Sensor.hasSensor()) - sht31Sensor.getMetrics(&m); + valid = sht31Sensor.getMetrics(&m); if (lps22hbSensor.hasSensor()) - lps22hbSensor.getMetrics(&m); + valid = lps22hbSensor.getMetrics(&m); if (shtc3Sensor.hasSensor()) - shtc3Sensor.getMetrics(&m); + valid = shtc3Sensor.getMetrics(&m); if (bmp280Sensor.hasSensor()) - bmp280Sensor.getMetrics(&m); + valid = bmp280Sensor.getMetrics(&m); if (bme280Sensor.hasSensor()) - bme280Sensor.getMetrics(&m); + valid = bme280Sensor.getMetrics(&m); if (bme680Sensor.hasSensor()) - bme680Sensor.getMetrics(&m); + valid = bme680Sensor.getMetrics(&m); if (mcp9808Sensor.hasSensor()) - mcp9808Sensor.getMetrics(&m); + valid = mcp9808Sensor.getMetrics(&m); if (ina219Sensor.hasSensor()) - ina219Sensor.getMetrics(&m); + valid = ina219Sensor.getMetrics(&m); if (ina260Sensor.hasSensor()) - ina260Sensor.getMetrics(&m); + valid = ina260Sensor.getMetrics(&m); - LOG_INFO( - "(Sending): barometric_pressure=%f, current=%f, gas_resistance=%f, relative_humidity=%f, temperature=%f, voltage=%f\n", - m.variant.environment_metrics.barometric_pressure, m.variant.environment_metrics.current, - m.variant.environment_metrics.gas_resistance, m.variant.environment_metrics.relative_humidity, - m.variant.environment_metrics.temperature, m.variant.environment_metrics.voltage); + if (valid) { + LOG_INFO("(Sending): barometric_pressure=%f, current=%f, gas_resistance=%f, relative_humidity=%f, temperature=%f, " + "voltage=%f\n", + m.variant.environment_metrics.barometric_pressure, m.variant.environment_metrics.current, + m.variant.environment_metrics.gas_resistance, m.variant.environment_metrics.relative_humidity, + m.variant.environment_metrics.temperature, m.variant.environment_metrics.voltage); - sensor_read_error_count = 0; + sensor_read_error_count = 0; - meshtastic_MeshPacket *p = allocDataProtobuf(m); - p->to = dest; - p->decoded.want_response = false; - if (config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR) - p->priority = meshtastic_MeshPacket_Priority_RELIABLE; - else - p->priority = meshtastic_MeshPacket_Priority_MIN; - // release previous packet before occupying a new spot - if (lastMeasurementPacket != nullptr) - packetPool.release(lastMeasurementPacket); + meshtastic_MeshPacket *p = allocDataProtobuf(m); + p->to = dest; + p->decoded.want_response = false; + if (config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR) + p->priority = meshtastic_MeshPacket_Priority_RELIABLE; + else + p->priority = meshtastic_MeshPacket_Priority_MIN; + // release previous packet before occupying a new spot + if (lastMeasurementPacket != nullptr) + packetPool.release(lastMeasurementPacket); - lastMeasurementPacket = packetPool.allocCopy(*p); - if (phoneOnly) { - LOG_INFO("Sending packet to phone\n"); - service.sendToPhone(p); - } else { - LOG_INFO("Sending packet to mesh\n"); - service.sendToMesh(p, RX_SRC_LOCAL, true); + lastMeasurementPacket = packetPool.allocCopy(*p); + if (phoneOnly) { + LOG_INFO("Sending packet to phone\n"); + service.sendToPhone(p); + } else { + LOG_INFO("Sending packet to mesh\n"); + service.sendToMesh(p, RX_SRC_LOCAL, true); + } } - return true; -} + return valid; +} \ No newline at end of file diff --git a/src/modules/Telemetry/EnvironmentTelemetry.h b/src/modules/Telemetry/EnvironmentTelemetry.h index 3340f8751..d6cd2137f 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.h +++ b/src/modules/Telemetry/EnvironmentTelemetry.h @@ -39,5 +39,6 @@ class EnvironmentTelemetryModule : private concurrency::OSThread, public Protobu meshtastic_MeshPacket *lastMeasurementPacket; uint32_t sendToPhoneIntervalMs = SECONDS_IN_MINUTE * 1000; // Send to phone every minute uint32_t lastSentToMesh = 0; + uint32_t lastSentToPhone = 0; uint32_t sensor_read_error_count = 0; }; diff --git a/src/modules/Telemetry/Sensor/BME680Sensor.cpp b/src/modules/Telemetry/Sensor/BME680Sensor.cpp index 6e28aac06..5b32645e6 100644 --- a/src/modules/Telemetry/Sensor/BME680Sensor.cpp +++ b/src/modules/Telemetry/Sensor/BME680Sensor.cpp @@ -6,21 +6,41 @@ BME680Sensor::BME680Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BME680, "BME680") {} +int32_t BME680Sensor::runTrigger() +{ + if (!bme680.run()) { + checkStatus("runTrigger"); + } + return 35; +} + int32_t BME680Sensor::runOnce() { - LOG_INFO("Init sensor: %s with the BSEC Library\n", sensorName); + if (!hasSensor()) { return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; } - bme680.begin(nodeTelemetrySensorsMap[sensorType], Wire); + if (!bme680.begin(nodeTelemetrySensorsMap[sensorType], Wire)) + checkStatus("begin"); + if (bme680.status == BSEC_OK) { - bme680.setConfig(Default_H2S_NonH2S_config); - loadState(); - bme680.updateSubscription(sensorList, 13, BSEC_SAMPLE_RATE_LP); status = 1; + if (!bme680.setConfig(bsec_config_iaq)) { + checkStatus("setConfig"); + status = 0; + } + loadState(); + if (!bme680.updateSubscription(sensorList, ARRAY_LEN(sensorList), BSEC_SAMPLE_RATE_LP)) { + checkStatus("updateSubscription"); + status = 0; + } + LOG_INFO("Init sensor: %s with the BSEC Library version %d.%d.%d.%d \n", sensorName, bme680.version.major, + bme680.version.minor, bme680.version.major_bugfix, bme680.version.minor_bugfix); } else { status = 0; } + if (status == 0) + LOG_DEBUG("BME680Sensor::runOnce: bme680.status %d\n", bme680.status); return initI2CSensor(); } @@ -29,8 +49,8 @@ void BME680Sensor::setup() {} bool BME680Sensor::getMetrics(meshtastic_Telemetry *measurement) { - bme680.run(); - + if (bme680.getData(BSEC_OUTPUT_RAW_PRESSURE).signal == 0) + return false; measurement->variant.environment_metrics.temperature = bme680.getData(BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE).signal; measurement->variant.environment_metrics.relative_humidity = bme680.getData(BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY).signal; @@ -106,4 +126,17 @@ void BME680Sensor::updateState() #else LOG_ERROR("ERROR: Filesystem not implemented\n"); #endif -} \ No newline at end of file +} + +void BME680Sensor::checkStatus(String functionName) +{ + if (bme680.status < BSEC_OK) + LOG_ERROR("%s BSEC2 code: %s\n", functionName.c_str(), String(bme680.status).c_str()); + else if (bme680.status > BSEC_OK) + LOG_WARN("%s BSEC2 code: %s\n", functionName.c_str(), String(bme680.status).c_str()); + + if (bme680.sensor.status < BME68X_OK) + LOG_ERROR("%s BME68X code: %s\n", functionName.c_str(), String(bme680.sensor.status).c_str()); + else if (bme680.sensor.status > BME68X_OK) + LOG_WARN("%s BME68X code: %s\n", functionName.c_str(), String(bme680.sensor.status).c_str()); +} diff --git a/src/modules/Telemetry/Sensor/BME680Sensor.h b/src/modules/Telemetry/Sensor/BME680Sensor.h index 6b45a76f4..06e24b1a9 100644 --- a/src/modules/Telemetry/Sensor/BME680Sensor.h +++ b/src/modules/Telemetry/Sensor/BME680Sensor.h @@ -4,7 +4,7 @@ #define STATE_SAVE_PERIOD UINT32_C(360 * 60 * 1000) // That's 6 hours worth of millis() -#include "config/Default_H2S_NonH2S/Default_H2S_NonH2S.h" +#include "bme680_iaq_33v_3s_4d/bsec_iaq.h" class BME680Sensor : virtual public TelemetrySensor { @@ -17,24 +17,22 @@ class BME680Sensor : virtual public TelemetrySensor uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE] = {0}; uint8_t accuracy = 0; uint16_t stateUpdateCounter = 0; - bsec_virtual_sensor_t sensorList[13] = {BSEC_OUTPUT_IAQ, - BSEC_OUTPUT_STATIC_IAQ, - BSEC_OUTPUT_CO2_EQUIVALENT, - BSEC_OUTPUT_BREATH_VOC_EQUIVALENT, - BSEC_OUTPUT_RAW_TEMPERATURE, - BSEC_OUTPUT_RAW_PRESSURE, - BSEC_OUTPUT_RAW_HUMIDITY, - BSEC_OUTPUT_RAW_GAS, - BSEC_OUTPUT_STABILIZATION_STATUS, - BSEC_OUTPUT_RUN_IN_STATUS, - BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE, - BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, - BSEC_OUTPUT_GAS_PERCENTAGE}; + bsecSensor sensorList[9] = {BSEC_OUTPUT_IAQ, + BSEC_OUTPUT_RAW_TEMPERATURE, + BSEC_OUTPUT_RAW_PRESSURE, + BSEC_OUTPUT_RAW_HUMIDITY, + BSEC_OUTPUT_RAW_GAS, + BSEC_OUTPUT_STABILIZATION_STATUS, + BSEC_OUTPUT_RUN_IN_STATUS, + BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE, + BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY}; void loadState(); void updateState(); + void checkStatus(String functionName); public: BME680Sensor(); + int32_t runTrigger(); virtual int32_t runOnce() override; virtual bool getMetrics(meshtastic_Telemetry *measurement) override; }; \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/INA219Sensor.cpp b/src/modules/Telemetry/Sensor/INA219Sensor.cpp index bffa1e367..1dd7f7f2c 100644 --- a/src/modules/Telemetry/Sensor/INA219Sensor.cpp +++ b/src/modules/Telemetry/Sensor/INA219Sensor.cpp @@ -12,8 +12,12 @@ int32_t INA219Sensor::runOnce() if (!hasSensor()) { return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; } - ina219 = Adafruit_INA219(nodeTelemetrySensorsMap[sensorType]); - status = ina219.begin(); + if (!ina219.success()) { + ina219 = Adafruit_INA219(nodeTelemetrySensorsMap[sensorType]); + status = ina219.begin(); + } else { + status = ina219.success(); + } return initI2CSensor(); } @@ -24,4 +28,9 @@ bool INA219Sensor::getMetrics(meshtastic_Telemetry *measurement) measurement->variant.environment_metrics.voltage = ina219.getBusVoltage_V(); measurement->variant.environment_metrics.current = ina219.getCurrent_mA(); return true; +} + +uint16_t INA219Sensor::getBusVoltageMv() +{ + return lround(ina219.getBusVoltage_V() * 1000); } \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/INA219Sensor.h b/src/modules/Telemetry/Sensor/INA219Sensor.h index dc6c0a5af..f11a571cc 100644 --- a/src/modules/Telemetry/Sensor/INA219Sensor.h +++ b/src/modules/Telemetry/Sensor/INA219Sensor.h @@ -1,8 +1,9 @@ #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" +#include "VoltageSensor.h" #include -class INA219Sensor : virtual public TelemetrySensor +class INA219Sensor : virtual public TelemetrySensor, VoltageSensor { private: Adafruit_INA219 ina219; @@ -14,4 +15,5 @@ class INA219Sensor : virtual public TelemetrySensor INA219Sensor(); virtual int32_t runOnce() override; virtual bool getMetrics(meshtastic_Telemetry *measurement) override; + virtual uint16_t getBusVoltageMv() override; }; \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/INA260Sensor.cpp b/src/modules/Telemetry/Sensor/INA260Sensor.cpp index ee0256e62..034fecca0 100644 --- a/src/modules/Telemetry/Sensor/INA260Sensor.cpp +++ b/src/modules/Telemetry/Sensor/INA260Sensor.cpp @@ -12,7 +12,10 @@ int32_t INA260Sensor::runOnce() if (!hasSensor()) { return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; } - status = ina260.begin(nodeTelemetrySensorsMap[sensorType]); + + if (!status) { + status = ina260.begin(nodeTelemetrySensorsMap[sensorType]); + } return initI2CSensor(); } @@ -24,4 +27,9 @@ bool INA260Sensor::getMetrics(meshtastic_Telemetry *measurement) measurement->variant.environment_metrics.voltage = ina260.readBusVoltage() / 1000; measurement->variant.environment_metrics.current = ina260.readCurrent(); return true; +} + +uint16_t INA260Sensor::getBusVoltageMv() +{ + return lround(ina260.readBusVoltage()); } \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/INA260Sensor.h b/src/modules/Telemetry/Sensor/INA260Sensor.h index 1dcb596e6..8ea532697 100644 --- a/src/modules/Telemetry/Sensor/INA260Sensor.h +++ b/src/modules/Telemetry/Sensor/INA260Sensor.h @@ -1,8 +1,9 @@ #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" +#include "VoltageSensor.h" #include -class INA260Sensor : virtual public TelemetrySensor +class INA260Sensor : virtual public TelemetrySensor, VoltageSensor { private: Adafruit_INA260 ina260 = Adafruit_INA260(); @@ -14,4 +15,5 @@ class INA260Sensor : virtual public TelemetrySensor INA260Sensor(); virtual int32_t runOnce() override; virtual bool getMetrics(meshtastic_Telemetry *measurement) override; + virtual uint16_t getBusVoltageMv() override; }; \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/TelemetrySensor.h b/src/modules/Telemetry/Sensor/TelemetrySensor.h index 7a579ef5c..dec81e061 100644 --- a/src/modules/Telemetry/Sensor/TelemetrySensor.h +++ b/src/modules/Telemetry/Sensor/TelemetrySensor.h @@ -1,9 +1,9 @@ #pragma once #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "NodeDB.h" -#include "main.h" #define DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000 +extern uint8_t nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1]; class TelemetrySensor { @@ -18,6 +18,7 @@ class TelemetrySensor const char *sensorName; meshtastic_TelemetrySensorType sensorType; unsigned status; + bool initialized = false; int32_t initI2CSensor() { @@ -28,6 +29,7 @@ class TelemetrySensor LOG_INFO("Opened %s sensor on default i2c bus\n", sensorName); setup(); } + initialized = true; return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; } virtual void setup(); @@ -36,5 +38,8 @@ class TelemetrySensor bool hasSensor() { return sensorType < sizeof(nodeTelemetrySensorsMap) && nodeTelemetrySensorsMap[sensorType] > 0; } virtual int32_t runOnce() = 0; + virtual bool isInitialized() { return initialized; } + virtual bool isRunning() { return status > 0; } + virtual bool getMetrics(meshtastic_Telemetry *measurement) = 0; -}; +}; \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/VoltageSensor.h b/src/modules/Telemetry/Sensor/VoltageSensor.h new file mode 100644 index 000000000..f2f28fb06 --- /dev/null +++ b/src/modules/Telemetry/Sensor/VoltageSensor.h @@ -0,0 +1,7 @@ +#pragma once + +class VoltageSensor +{ + public: + virtual uint16_t getBusVoltageMv() = 0; +}; \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/bme680_iaq_33v_3s_4d/bsec_iaq.c b/src/modules/Telemetry/Sensor/bme680_iaq_33v_3s_4d/bsec_iaq.c new file mode 100644 index 000000000..1f27e6c69 --- /dev/null +++ b/src/modules/Telemetry/Sensor/bme680_iaq_33v_3s_4d/bsec_iaq.c @@ -0,0 +1,82 @@ +#include "bsec_iaq.h" + +const uint8_t bsec_config_iaq[1974] = { + 0, 0, 4, 2, 189, 1, 0, 0, 0, 0, 0, 0, 158, 7, 0, 0, 176, 0, 1, 0, 0, 192, 168, 71, 64, + 49, 119, 76, 0, 0, 97, 69, 0, 0, 97, 69, 137, 65, 0, 191, 205, 204, 204, 190, 0, 0, 64, 191, 225, 122, + 148, 190, 10, 0, 3, 0, 0, 0, 96, 64, 23, 183, 209, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 205, 204, 204, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 128, 63, 82, 73, 157, 188, 95, 41, 203, 61, 118, 224, + 108, 63, 155, 230, 125, 63, 191, 14, 124, 63, 0, 0, 160, 65, 0, 0, 32, 66, 0, 0, 160, 65, 0, 0, 32, + 66, 0, 0, 32, 66, 0, 0, 160, 65, 0, 0, 32, 66, 0, 0, 160, 65, 8, 0, 2, 0, 236, 81, 133, 66, + 16, 0, 3, 0, 10, 215, 163, 60, 10, 215, 35, 59, 10, 215, 35, 59, 13, 0, 5, 0, 0, 0, 0, 0, 100, + 35, 41, 29, 86, 88, 0, 9, 0, 229, 208, 34, 62, 0, 0, 0, 0, 0, 0, 0, 0, 218, 27, 156, 62, 225, + 11, 67, 64, 0, 0, 160, 64, 0, 0, 0, 0, 0, 0, 0, 0, 94, 75, 72, 189, 93, 254, 159, 64, 66, 62, + 160, 191, 0, 0, 0, 0, 0, 0, 0, 0, 33, 31, 180, 190, 138, 176, 97, 64, 65, 241, 99, 190, 0, 0, 0, + 0, 0, 0, 0, 0, 167, 121, 71, 61, 165, 189, 41, 192, 184, 30, 189, 64, 12, 0, 10, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 5, 11, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, + 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, + 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, + 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, + 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, + 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, + 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, + 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, + 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, + 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, + 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, + 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, + 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, + 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, + 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, + 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, + 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, + 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, + 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, + 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, + 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, + 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 10, 10, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, + 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 0, 88, 1, 254, + 0, 2, 1, 5, 48, 117, 100, 0, 44, 1, 112, 23, 151, 7, 132, 3, 197, 0, 92, 4, 144, 1, 64, 1, 64, + 1, 144, 1, 48, 117, 48, 117, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, 48, 117, 100, 0, + 100, 0, 48, 117, 48, 117, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 100, 0, 100, 0, 100, 0, 100, 0, 48, + 117, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, 100, 0, 100, 0, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, + 1, 44, 1, 44, 1, 44, 1, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 112, 23, 112, 23, 112, 23, 112, 23, + 8, 7, 8, 7, 8, 7, 8, 7, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 112, 23, 112, 23, 112, 23, 112, 23, 255, 255, 255, 255, + 220, 5, 220, 5, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 220, 5, 220, 5, 220, 5, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 44, 1, 0, 5, 10, 5, + 0, 2, 0, 10, 0, 30, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 64, 1, 100, 0, 100, 0, + 100, 0, 200, 0, 200, 0, 200, 0, 64, 1, 64, 1, 64, 1, 10, 0, 0, 0, 0, 0, 21, 122, 0, 0}; diff --git a/src/modules/Telemetry/Sensor/bme680_iaq_33v_3s_4d/bsec_iaq.h b/src/modules/Telemetry/Sensor/bme680_iaq_33v_3s_4d/bsec_iaq.h new file mode 100644 index 000000000..cdd209ae5 --- /dev/null +++ b/src/modules/Telemetry/Sensor/bme680_iaq_33v_3s_4d/bsec_iaq.h @@ -0,0 +1,3 @@ +#include + +extern const uint8_t bsec_config_iaq[1974]; diff --git a/src/modules/esp32/StoreForwardModule.cpp b/src/modules/esp32/StoreForwardModule.cpp index 38e983669..767e1fb2b 100644 --- a/src/modules/esp32/StoreForwardModule.cpp +++ b/src/modules/esp32/StoreForwardModule.cpp @@ -36,8 +36,6 @@ int32_t StoreForwardModule::runOnce() this->packetHistoryTXQueue_index++; } } - LOG_DEBUG("*** SF bitrate = %f bytes / sec\n", myNodeInfo.bitrate); - } else if ((millis() - lastHeartbeat > (heartbeatInterval * 1000)) && airTime->isTxAllowedChannelUtil(true)) { lastHeartbeat = millis(); LOG_INFO("*** Sending heartbeat\n"); @@ -266,7 +264,6 @@ ProcessMessage StoreForwardModule::handleReceived(const meshtastic_MeshPacket &m storeForwardModule->historyAdd(mp); LOG_INFO("*** S&F stored. Message history contains %u records now.\n", this->packetHistoryCurrent); } - } else if (mp.decoded.portnum == meshtastic_PortNum_STORE_FORWARD_APP) { auto &p = mp.decoded; meshtastic_StoreAndForward scratch; diff --git a/src/platform/nrf52/main-nrf52.cpp b/src/platform/nrf52/main-nrf52.cpp index 36ddefeb4..c630aa13b 100644 --- a/src/platform/nrf52/main-nrf52.cpp +++ b/src/platform/nrf52/main-nrf52.cpp @@ -172,6 +172,10 @@ void cpuDeepSleep(uint32_t msecToWake) setBluetoothEnable(false); #ifdef RAK4630 digitalWrite(PIN_3V3_EN, LOW); +#ifndef USE_EINK + // RAK-12039 set pin for Air quality sensor + digitalWrite(AQ_SET_PIN, LOW); +#endif #endif // FIXME, use system off mode with ram retention for key state? // FIXME, use non-init RAM per @@ -197,4 +201,4 @@ void clearBonds() nrf52Bluetooth->setup(); } nrf52Bluetooth->clearBonds(); -} +} \ No newline at end of file diff --git a/src/platform/rp2040/architecture.h b/src/platform/rp2040/architecture.h index c5a2ecdec..772e4b1af 100644 --- a/src/platform/rp2040/architecture.h +++ b/src/platform/rp2040/architecture.h @@ -2,6 +2,18 @@ #define ARCH_RP2040 -#if defined(PRIVATE_HW) -#define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW +#ifndef HAS_TELEMETRY +#define HAS_TELEMETRY 1 +#endif +#ifndef HAS_SENSOR +#define HAS_SENSOR 1 +#endif +#ifndef HAS_RADIO +#define HAS_RADIO 1 +#endif + +#if defined(RPI_PICO) +#define HW_VENDOR meshtastic_HardwareModel_RPI_PICO +#elif defined(RAK11310) +#define HW_VENDOR meshtastic_HardwareModel_RAK11310 #endif \ No newline at end of file diff --git a/src/platform/rp2040/main-rp2040.cpp b/src/platform/rp2040/main-rp2040.cpp index af200f961..5e24bf03c 100644 --- a/src/platform/rp2040/main-rp2040.cpp +++ b/src/platform/rp2040/main-rp2040.cpp @@ -21,10 +21,10 @@ void getMacAddr(uint8_t *dmac) { pico_unique_board_id_t src; pico_get_unique_board_id(&src); - dmac[5] = src.id[0]; - dmac[4] = src.id[1]; - dmac[3] = src.id[2]; - dmac[2] = src.id[3]; - dmac[1] = src.id[4]; - dmac[0] = src.id[5]; -} + dmac[5] = src.id[7]; + dmac[4] = src.id[6]; + dmac[3] = src.id[5]; + dmac[2] = src.id[4]; + dmac[1] = src.id[3]; + dmac[0] = src.id[2]; +} \ No newline at end of file diff --git a/src/platform/stm32wl/InternalFileSystem.cpp b/src/platform/stm32wl/InternalFileSystem.cpp new file mode 100644 index 000000000..950ceb0cd --- /dev/null +++ b/src/platform/stm32wl/InternalFileSystem.cpp @@ -0,0 +1,141 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 hathach for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "InternalFileSystem.h" +#include + +//--------------------------------------------------------------------+ +// LFS Disk IO +//--------------------------------------------------------------------+ + +static inline uint32_t lba2addr(uint32_t block) +{ + return ((uint32_t)LFS_FLASH_ADDR) + block * LFS_BLOCK_SIZE; +} + +static int _internal_flash_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) +{ + (void)c; + + uint32_t addr = lba2addr(block) + off; + uint8_t prom; + + for (int i = 0; i < size; i++) { + prom = EEPROM.read(addr + i); + memcpy((char *)buffer + i, &prom, 1); + } + return 0; +} + +// Program a region in a block. The block must have previously +// been erased. Negative error codes are propogated to the user. +// May return LFS_ERR_CORRUPT if the block should be considered bad. +static int _internal_flash_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) +{ + (void)c; + + uint32_t addr = lba2addr(block) + off; + uint8_t prom; + + for (int i = 0; i < size; i++) { + memcpy(&prom, (char *)buffer + i, 1); + EEPROM.update(addr + i, prom); + } + return 0; +} + +// Erase a block. A block must be erased before being programmed. +// The state of an erased block is undefined. Negative error codes +// are propogated to the user. +// May return LFS_ERR_CORRUPT if the block should be considered bad. +static int _internal_flash_erase(const struct lfs_config *c, lfs_block_t block) +{ + (void)c; + + uint32_t addr = lba2addr(block); + + // implement as write 0xff to whole block address + for (int i = 0; i < LFS_BLOCK_SIZE; i++) { + EEPROM.update(addr, 0xff); + } + + return 0; +} + +// Sync the state of the underlying block device. Negative error codes +// are propogated to the user. +static int _internal_flash_sync(const struct lfs_config *c) +{ + // we don't use a ram cache, this is a noop + return 0; +} + +static struct lfs_config _InternalFSConfig = {.context = NULL, + + .read = _internal_flash_read, + .prog = _internal_flash_prog, + .erase = _internal_flash_erase, + .sync = _internal_flash_sync, + + .read_size = LFS_CACHE_SIZE, + .prog_size = LFS_CACHE_SIZE, + .block_size = LFS_BLOCK_SIZE, + .block_count = LFS_FLASH_TOTAL_SIZE / LFS_BLOCK_SIZE, + .block_cycles = + 500, // protection against wear leveling (suggested values between 100-1000) + .cache_size = LFS_CACHE_SIZE, + .lookahead_size = LFS_CACHE_SIZE, + + .read_buffer = lfs_read_buffer, + .prog_buffer = lfs_prog_buffer, + .lookahead_buffer = lfs_lookahead_buffer}; + +InternalFileSystem InternalFS; + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +InternalFileSystem::InternalFileSystem(void) : LittleFS(&_InternalFSConfig) {} + +bool InternalFileSystem::begin(void) +{ + // failed to mount, erase all sector then format and mount again + if (!LittleFS::begin()) { + // Erase all sectors of internal flash region for Filesystem. + // implement as write 0xff to whole block address + for (uint32_t addr = LFS_FLASH_ADDR; addr < (LFS_FLASH_ADDR + LFS_FLASH_TOTAL_SIZE); addr++) { + EEPROM.update(addr, 0xff); + } + + // lfs format + this->format(); + + // mount again if still failed, give up + if (!LittleFS::begin()) + return false; + } + + return true; +} diff --git a/src/platform/stm32wl/InternalFileSystem.h b/src/platform/stm32wl/InternalFileSystem.h new file mode 100644 index 000000000..66344194e --- /dev/null +++ b/src/platform/stm32wl/InternalFileSystem.h @@ -0,0 +1,54 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 hathach for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef INTERNALFILESYSTEM_H_ +#define INTERNALFILESYSTEM_H_ + +#include "LittleFS.h" + +// The EEPROM Library assumes our usable flash area starts at logical 0 +#define LFS_FLASH_ADDR 0 + +// use the built in EEPROM emulation. Total Size is 2Kbyte +#define LFS_BLOCK_SIZE 128 // min. block size is 128 to fit CTZ pointers +#define LFS_CACHE_SIZE 16 + +#define LFS_FLASH_TOTAL_SIZE FLASH_PAGE_SIZE + +static uint8_t lfs_read_buffer[LFS_CACHE_SIZE] = {0}; +static uint8_t lfs_prog_buffer[LFS_CACHE_SIZE] = {0}; +static uint8_t lfs_lookahead_buffer[LFS_CACHE_SIZE] = {0}; + +class InternalFileSystem : public LittleFS +{ + public: + InternalFileSystem(void); + + // overwrite to also perform low level format (sector erase of whole flash region) + bool begin(void); +}; + +extern InternalFileSystem InternalFS; + +#endif /* INTERNALFILESYSTEM_H_ */ diff --git a/src/platform/stm32wl/LittleFS.cpp b/src/platform/stm32wl/LittleFS.cpp new file mode 100644 index 000000000..b1267d88a --- /dev/null +++ b/src/platform/stm32wl/LittleFS.cpp @@ -0,0 +1,258 @@ +#include +#include + +#include "LittleFS.h" + +using namespace LittleFS_Namespace; + +//--------------------------------------------------------------------+ +// Implementation +//--------------------------------------------------------------------+ + +LittleFS::LittleFS(void) : LittleFS(NULL) {} + +LittleFS::LittleFS(struct lfs_config *cfg) +{ + memset(&_lfs, 0, sizeof(_lfs)); + _lfs_cfg = cfg; + _mounted = false; + _mutex = xSemaphoreCreateMutexStatic(&this->_MutexStorageSpace); +} + +LittleFS::~LittleFS() {} + +// Initialize and mount the file system +// Return true if mounted successfully else probably corrupted. +// User should format the disk and try again +bool LittleFS::begin(struct lfs_config *cfg) +{ + _lockFS(); + + bool ret; + // not a loop, just an quick way to short-circuit on error + do { + if (_mounted) { + ret = true; + break; + } + if (cfg) { + _lfs_cfg = cfg; + } + if (nullptr == _lfs_cfg) { + ret = false; + break; + } + // actually attempt to mount, and log error if one occurs + int err = lfs_mount(&_lfs, _lfs_cfg); + PRINT_LFS_ERR(err); + _mounted = (err == LFS_ERR_OK); + ret = _mounted; + } while (0); + + _unlockFS(); + return ret; +} + +// Tear down and unmount file system +void LittleFS::end(void) +{ + _lockFS(); + + if (_mounted) { + _mounted = false; + int err = lfs_unmount(&_lfs); + PRINT_LFS_ERR(err); + (void)err; + } + + _unlockFS(); +} + +bool LittleFS::format(void) +{ + _lockFS(); + + int err = LFS_ERR_OK; + bool attemptMount = _mounted; + // not a loop, just an quick way to short-circuit on error + do { + // if already mounted: umount first -> format -> remount + if (_mounted) { + _mounted = false; + err = lfs_unmount(&_lfs); + if (LFS_ERR_OK != err) { + PRINT_LFS_ERR(err); + break; + } + } + err = lfs_format(&_lfs, _lfs_cfg); + if (LFS_ERR_OK != err) { + PRINT_LFS_ERR(err); + break; + } + + if (attemptMount) { + err = lfs_mount(&_lfs, _lfs_cfg); + if (LFS_ERR_OK != err) { + PRINT_LFS_ERR(err); + break; + } + _mounted = true; + } + // success! + } while (0); + + _unlockFS(); + return LFS_ERR_OK == err; +} + +// Open a file or folder +LittleFS_Namespace::File LittleFS::open(char const *filepath, uint8_t mode) +{ + // No lock is required here ... the File() object will synchronize with the mutex provided + return LittleFS_Namespace::File(filepath, mode, *this); +} + +// Check if file or folder exists +bool LittleFS::exists(char const *filepath) +{ + struct lfs_info info; + _lockFS(); + + bool ret = (0 == lfs_stat(&_lfs, filepath, &info)); + + _unlockFS(); + return ret; +} + +// Create a directory, create intermediate parent if needed +bool LittleFS::mkdir(char const *filepath) +{ + bool ret = true; + const char *slash = filepath; + if (slash[0] == '/') + slash++; // skip root '/' + + _lockFS(); + + // make intermediate parent directory(ies) + while (NULL != (slash = strchr(slash, '/'))) { + char parent[slash - filepath + 1] = {0}; + memcpy(parent, filepath, slash - filepath); + + int rc = lfs_mkdir(&_lfs, parent); + if (rc != LFS_ERR_OK && rc != LFS_ERR_EXIST) { + PRINT_LFS_ERR(rc); + ret = false; + break; + } + slash++; + } + // make the final requested directory + if (ret) { + int rc = lfs_mkdir(&_lfs, filepath); + if (rc != LFS_ERR_OK && rc != LFS_ERR_EXIST) { + PRINT_LFS_ERR(rc); + ret = false; + } + } + + _unlockFS(); + return ret; +} + +// Remove a file +bool LittleFS::remove(char const *filepath) +{ + _lockFS(); + + int err = lfs_remove(&_lfs, filepath); + PRINT_LFS_ERR(err); + + _unlockFS(); + return LFS_ERR_OK == err; +} + +// Rename a file +bool LittleFS::rename(char const *oldfilepath, char const *newfilepath) +{ + _lockFS(); + + int err = lfs_rename(&_lfs, oldfilepath, newfilepath); + PRINT_LFS_ERR(err); + + _unlockFS(); + return LFS_ERR_OK == err; +} + +// Remove a folder +bool LittleFS::rmdir(char const *filepath) +{ + _lockFS(); + + int err = lfs_remove(&_lfs, filepath); + PRINT_LFS_ERR(err); + + _unlockFS(); + return LFS_ERR_OK == err; +} + +// Remove a folder recursively +bool LittleFS::rmdir_r(char const *filepath) +{ + /* adafruit: lfs is modified to remove non-empty folder, + According to below issue, comment these 2 line won't corrupt filesystem + at least when using LFS v1. If moving to LFS v2, see tracked issue + to see if issues (such as the orphans in threaded linked list) are resolved. + https://github.com/ARMmbed/littlefs/issues/43 + */ + _lockFS(); + + int err = lfs_remove(&_lfs, filepath); + PRINT_LFS_ERR(err); + + _unlockFS(); + return LFS_ERR_OK == err; +} + +//------------- Debug -------------// +#if CFG_DEBUG + +const char *dbg_strerr_lfs(int32_t err) +{ + switch (err) { + case LFS_ERR_OK: + return "LFS_ERR_OK"; + case LFS_ERR_IO: + return "LFS_ERR_IO"; + case LFS_ERR_CORRUPT: + return "LFS_ERR_CORRUPT"; + case LFS_ERR_NOENT: + return "LFS_ERR_NOENT"; + case LFS_ERR_EXIST: + return "LFS_ERR_EXIST"; + case LFS_ERR_NOTDIR: + return "LFS_ERR_NOTDIR"; + case LFS_ERR_ISDIR: + return "LFS_ERR_ISDIR"; + case LFS_ERR_NOTEMPTY: + return "LFS_ERR_NOTEMPTY"; + case LFS_ERR_BADF: + return "LFS_ERR_BADF"; + case LFS_ERR_INVAL: + return "LFS_ERR_INVAL"; + case LFS_ERR_NOSPC: + return "LFS_ERR_NOSPC"; + case LFS_ERR_NOMEM: + return "LFS_ERR_NOMEM"; + + default: + static char errcode[10]; + sprintf(errcode, "%ld", err); + return errcode; + } + + return NULL; +} + +#endif diff --git a/src/platform/stm32wl/LittleFS.h b/src/platform/stm32wl/LittleFS.h new file mode 100644 index 000000000..4a0b01af2 --- /dev/null +++ b/src/platform/stm32wl/LittleFS.h @@ -0,0 +1,85 @@ + +#ifndef LITTLEFS_H_ +#define LITTLEFS_H_ + +#include + +#include "lfs.h" + +#include "LittleFS_File.h" + +#include "FreeRTOS.h" // tied to FreeRTOS for serialization +#include "semphr.h" + +class LittleFS +{ + public: + LittleFS(void); + explicit LittleFS(struct lfs_config *cfg); + virtual ~LittleFS(); + + bool begin(struct lfs_config *cfg = NULL); + void end(void); + + // Open the specified file/directory with the supplied mode (e.g. read or + // write, etc). Returns a File object for interacting with the file. + // Note that currently only one file can be open at a time. + LittleFS_Namespace::File open(char const *filename, uint8_t mode = LittleFS_Namespace::FILE_O_READ); + + // Methods to determine if the requested file path exists. + bool exists(char const *filepath); + + // Create the requested directory hierarchy--if intermediate directories + // do not exist they will be created. + bool mkdir(char const *filepath); + + // Delete the file. + bool remove(char const *filepath); + + // Rename the file. + bool rename(char const *oldfilepath, char const *newfilepath); + + // Delete a folder (must be empty) + bool rmdir(char const *filepath); + + // Delete a folder (recursively) + bool rmdir_r(char const *filepath); + + // format file system + bool format(void); + + /*------------------------------------------------------------------*/ + /* INTERNAL USAGE ONLY + * Although declare as public, it is meant to be invoked by internal + * code. User should not call these directly + *------------------------------------------------------------------*/ + lfs_t *_getFS(void) { return &_lfs; } + void _lockFS(void) { xSemaphoreTake(_mutex, portMAX_DELAY); } + void _unlockFS(void) { xSemaphoreGive(_mutex); } + + protected: + bool _mounted; + struct lfs_config *_lfs_cfg; + lfs_t _lfs; + SemaphoreHandle_t _mutex; + + private: + StaticSemaphore_t _MutexStorageSpace; +}; + +#if !CFG_DEBUG +#define VERIFY_LFS(...) _GET_3RD_ARG(__VA_ARGS__, VERIFY_ERR_2ARGS, VERIFY_ERR_1ARGS)(__VA_ARGS__, NULL) +#define PRINT_LFS_ERR(_err) +#else +#define VERIFY_LFS(...) _GET_3RD_ARG(__VA_ARGS__, VERIFY_ERR_2ARGS, VERIFY_ERR_1ARGS)(__VA_ARGS__, dbg_strerr_lfs) +#define PRINT_LFS_ERR(_err) \ + do { \ + if (_err) { \ + VERIFY_MESS((long int)_err, dbg_strerr_lfs); \ + } \ + } while (0) // LFS_ERR are of type int, VERIFY_MESS expects long_int + +const char *dbg_strerr_lfs(int32_t err); +#endif + +#endif /* LITTLEFS_H_ */ diff --git a/src/platform/stm32wl/LittleFS_File.cpp b/src/platform/stm32wl/LittleFS_File.cpp new file mode 100644 index 000000000..cffb924e1 --- /dev/null +++ b/src/platform/stm32wl/LittleFS_File.cpp @@ -0,0 +1,362 @@ +#include + +#include "LittleFS.h" + +#include + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +using namespace LittleFS_Namespace; + +File::File(LittleFS &fs) +{ + _fs = &fs; + _is_dir = false; + _name[0] = 0; + _dir_path = NULL; + + _dir = NULL; + _file = NULL; +} + +File::File(char const *filename, uint8_t mode, LittleFS &fs) : File(fs) +{ + // public constructor calls public API open(), which will obtain the mutex + this->open(filename, mode); +} + +bool File::_open_file(char const *filepath, uint8_t mode) +{ + int flags = (mode == FILE_O_READ) ? LFS_O_RDONLY : (mode == FILE_O_WRITE) ? (LFS_O_RDWR | LFS_O_CREAT) : 0; + + if (flags) { + _file = (lfs_file_t *)malloc(sizeof(lfs_file_t)); + if (!_file) + return false; + + int rc = lfs_file_open(_fs->_getFS(), _file, filepath, flags); + + if (rc) { + // failed to open + PRINT_LFS_ERR(rc); + return false; + } + + // move to end of file + if (mode == FILE_O_WRITE) + lfs_file_seek(_fs->_getFS(), _file, 0, LFS_SEEK_END); + + _is_dir = false; + } + + return true; +} + +bool File::_open_dir(char const *filepath) +{ + _dir = (lfs_dir_t *)malloc(sizeof(lfs_dir_t)); + if (!_dir) + return false; + + int rc = lfs_dir_open(_fs->_getFS(), _dir, filepath); + + if (rc) { + // failed to open + PRINT_LFS_ERR(rc); + return false; + } + + _is_dir = true; + + _dir_path = (char *)malloc(strlen(filepath) + 1); + strcpy(_dir_path, filepath); + + return true; +} + +bool File::open(char const *filepath, uint8_t mode) +{ + bool ret = false; + _fs->_lockFS(); + + ret = this->_open(filepath, mode); + + _fs->_unlockFS(); + return ret; +} + +bool File::_open(char const *filepath, uint8_t mode) +{ + bool ret = false; + + // close if currently opened + if (this->isOpen()) + _close(); + + struct lfs_info info; + int rc = lfs_stat(_fs->_getFS(), filepath, &info); + + if (LFS_ERR_OK == rc) { + // file existed, open file or directory accordingly + ret = (info.type == LFS_TYPE_REG) ? _open_file(filepath, mode) : _open_dir(filepath); + } else if (LFS_ERR_NOENT == rc) { + // file not existed, only proceed with FILE_O_WRITE mode + if (mode == FILE_O_WRITE) + ret = _open_file(filepath, mode); + } else { + PRINT_LFS_ERR(rc); + } + + // save bare file name + if (ret) { + char const *splash = strrchr(filepath, '/'); + strncpy(_name, splash ? (splash + 1) : filepath, LFS_NAME_MAX); + } + return ret; +} + +size_t File::write(uint8_t ch) +{ + return write(&ch, 1); +} + +size_t File::write(uint8_t const *buf, size_t size) +{ + lfs_ssize_t wrcount = 0; + _fs->_lockFS(); + + if (!this->_is_dir) { + wrcount = lfs_file_write(_fs->_getFS(), _file, buf, size); + if (wrcount < 0) { + wrcount = 0; + } + } + + _fs->_unlockFS(); + return wrcount; +} + +int File::read(void) +{ + // this thin wrapper relies on called function to synchronize + int ret = -1; + uint8_t ch; + if (read(&ch, 1) > 0) { + ret = static_cast(ch); + } + return ret; +} + +int File::read(void *buf, uint16_t nbyte) +{ + int ret = 0; + _fs->_lockFS(); + + if (!this->_is_dir) { + ret = lfs_file_read(_fs->_getFS(), _file, buf, nbyte); + } + + _fs->_unlockFS(); + return ret; +} + +int File::peek(void) +{ + int ret = -1; + _fs->_lockFS(); + + if (!this->_is_dir) { + uint32_t pos = lfs_file_tell(_fs->_getFS(), _file); + uint8_t ch = 0; + if (lfs_file_read(_fs->_getFS(), _file, &ch, 1) > 0) { + ret = static_cast(ch); + } + (void)lfs_file_seek(_fs->_getFS(), _file, pos, LFS_SEEK_SET); + } + + _fs->_unlockFS(); + return ret; +} + +int File::available(void) +{ + int ret = 0; + _fs->_lockFS(); + + if (!this->_is_dir) { + uint32_t size = lfs_file_size(_fs->_getFS(), _file); + uint32_t pos = lfs_file_tell(_fs->_getFS(), _file); + ret = size - pos; + } + + _fs->_unlockFS(); + return ret; +} + +bool File::seek(uint32_t pos) +{ + bool ret = false; + _fs->_lockFS(); + + if (!this->_is_dir) { + ret = lfs_file_seek(_fs->_getFS(), _file, pos, LFS_SEEK_SET) >= 0; + } + + _fs->_unlockFS(); + return ret; +} + +uint32_t File::position(void) +{ + uint32_t ret = 0; + _fs->_lockFS(); + + if (!this->_is_dir) { + ret = lfs_file_tell(_fs->_getFS(), _file); + } + + _fs->_unlockFS(); + return ret; +} + +uint32_t File::size(void) +{ + uint32_t ret = 0; + _fs->_lockFS(); + + if (!this->_is_dir) { + ret = lfs_file_size(_fs->_getFS(), _file); + } + + _fs->_unlockFS(); + return ret; +} + +bool File::truncate(uint32_t pos) +{ + int32_t ret = LFS_ERR_ISDIR; + _fs->_lockFS(); + if (!this->_is_dir) { + ret = lfs_file_truncate(_fs->_getFS(), _file, pos); + } + _fs->_unlockFS(); + return (ret == 0); +} + +bool File::truncate(void) +{ + int32_t ret = LFS_ERR_ISDIR; + _fs->_lockFS(); + if (!this->_is_dir) { + uint32_t pos = lfs_file_tell(_fs->_getFS(), _file); + ret = lfs_file_truncate(_fs->_getFS(), _file, pos); + } + _fs->_unlockFS(); + return (ret == 0); +} + +void File::flush(void) +{ + _fs->_lockFS(); + + if (!this->_is_dir) { + lfs_file_sync(_fs->_getFS(), _file); + } + + _fs->_unlockFS(); + return; +} + +void File::close(void) +{ + _fs->_lockFS(); + this->_close(); + _fs->_unlockFS(); +} + +void File::_close(void) +{ + if (this->isOpen()) { + if (this->_is_dir) { + lfs_dir_close(_fs->_getFS(), _dir); + free(_dir); + _dir = NULL; + + if (this->_dir_path) + free(_dir_path); + _dir_path = NULL; + } else { + lfs_file_close(this->_fs->_getFS(), _file); + free(_file); + _file = NULL; + } + } +} + +File::operator bool(void) +{ + return isOpen(); +} + +bool File::isOpen(void) +{ + return (_file != NULL) || (_dir != NULL); +} + +// WARNING -- although marked as `const`, the values pointed +// to may change. For example, if the same File +// object has `open()` called with a different +// file or directory name, this same pointer will +// suddenly (unexpectedly?) have different values. +char const *File::name(void) +{ + return this->_name; +} + +bool File::isDirectory(void) +{ + return this->_is_dir; +} + +File File::openNextFile(uint8_t mode) +{ + _fs->_lockFS(); + + File ret(*_fs); + if (this->_is_dir) { + struct lfs_info info; + int rc; + + // lfs_dir_read returns 0 when reaching end of directory, 1 if found an entry + // Skip the "." and ".." entries ... + do { + rc = lfs_dir_read(_fs->_getFS(), _dir, &info); + } while (rc == 1 && (!strcmp(".", info.name) || !strcmp("..", info.name))); + + if (rc == 1) { + // string cat name with current folder + char filepath[strlen(_dir_path) + 1 + strlen(info.name) + 1]; // potential for significant stack usage + strcpy(filepath, _dir_path); + if (!(_dir_path[0] == '/' && _dir_path[1] == 0)) + strcat(filepath, "/"); // only add '/' if cwd is not root + strcat(filepath, info.name); + + (void)ret._open(filepath, mode); // return value is ignored ... caller is expected to check isOpened() + } else if (rc < 0) { + PRINT_LFS_ERR(rc); + } + } + _fs->_unlockFS(); + return ret; +} + +void File::rewindDirectory(void) +{ + _fs->_lockFS(); + if (this->_is_dir) { + lfs_dir_rewind(_fs->_getFS(), _dir); + } + _fs->_unlockFS(); +} diff --git a/src/platform/stm32wl/LittleFS_File.h b/src/platform/stm32wl/LittleFS_File.h new file mode 100644 index 000000000..e88a2790d --- /dev/null +++ b/src/platform/stm32wl/LittleFS_File.h @@ -0,0 +1,82 @@ +#ifndef LITTLEFS_FILE_H_ +#define LITTLEFS_FILE_H_ + +// Forward declaration +class LittleFS; + +namespace LittleFS_Namespace +{ + +// avoid conflict with other FileSystem FILE_READ/FILE_WRITE +enum { + FILE_O_READ = 0, + FILE_O_WRITE = 1, +}; + +class File : public Stream +{ + public: + explicit File(LittleFS &fs); + File(char const *filename, uint8_t mode, LittleFS &fs); + + public: + bool open(char const *filename, uint8_t mode); + + //------------- Stream API -------------// + virtual size_t write(uint8_t ch); + virtual size_t write(uint8_t const *buf, size_t size); + size_t write(const char *str) + { + if (str == NULL) + return 0; + return write((const uint8_t *)str, strlen(str)); + } + size_t write(const char *buffer, size_t size) { return write((const uint8_t *)buffer, size); } + + virtual int read(void); + int read(void *buf, uint16_t nbyte); + + virtual int peek(void); + virtual int available(void); + virtual void flush(void); + + bool seek(uint32_t pos); + uint32_t position(void); + uint32_t size(void); + + bool truncate(uint32_t pos); + bool truncate(void); + + void close(void); + + operator bool(void); + + bool isOpen(void); + char const *name(void); + + bool isDirectory(void); + File openNextFile(uint8_t mode = FILE_O_READ); + void rewindDirectory(void); + + private: + LittleFS *_fs; + + bool _is_dir; + + union { + lfs_file_t *_file; + lfs_dir_t *_dir; + }; + + char *_dir_path; + char _name[LFS_NAME_MAX + 1]; + + bool _open(char const *filepath, uint8_t mode); + bool _open_file(char const *filepath, uint8_t mode); + bool _open_dir(char const *filepath); + void _close(void); +}; + +} // namespace LittleFS_Namespace + +#endif /* LITTLEFS_FILE_H_ */ diff --git a/src/platform/stm32wl/architecture.h b/src/platform/stm32wl/architecture.h index dc7adc5ff..1c021903a 100644 --- a/src/platform/stm32wl/architecture.h +++ b/src/platform/stm32wl/architecture.h @@ -6,24 +6,19 @@ // defaults for STM32WL architecture // +#ifndef HAS_RADIO +#define HAS_RADIO 1 +#endif + // // set HW_VENDOR // #ifndef HW_VENDOR -#define HW_VENDOR HardwareModel_PRIVATE_HW +#define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW #endif -#ifdef __cplusplus -extern "C" { -#endif -void stm32wl_emulate_digitalWrite(long unsigned int pin, long unsigned int value); -int stm32wl_emulate_digitalRead(long unsigned int pin); -#ifdef __cplusplus -} -#endif - -/* virtual pins for stm32wl_emulate_digitalWrite() / stm32wl_emulate_digitalRead() to recognize */ +/* virtual pins */ #define SX126X_CS 1000 #define SX126X_DIO1 1001 #define SX126X_RESET 1003 diff --git a/src/platform/stm32wl/layer.c b/src/platform/stm32wl/layer.c deleted file mode 100644 index d6f073200..000000000 --- a/src/platform/stm32wl/layer.c +++ /dev/null @@ -1,65 +0,0 @@ -#include "architecture.h" -#include "stm32wlxx.h" -#include "stm32wlxx_hal.h" -#include - -void HardFault_Handler(void) -{ - asm("bkpt"); -} - -void stm32wl_emulate_digitalWrite(long unsigned int pin, long unsigned int value) -{ - switch (pin) { - case SX126X_CS: /* active low */ - if (value) - LL_PWR_UnselectSUBGHZSPI_NSS(); - else - LL_PWR_SelectSUBGHZSPI_NSS(); - break; - case SX126X_RESET: /* active low */ - if (value) - LL_RCC_RF_DisableReset(); - else { - LL_RCC_RF_EnableReset(); - LL_RCC_HSE_EnableTcxo(); - LL_RCC_HSE_Enable(); - while (!LL_RCC_HSE_IsReady()) - ; - } - break; - default: - asm("bkpt"); - break; - } -} - -static bool irq_happened; - -void SUBGHZ_Radio_IRQHandler(void) -{ - NVIC_DisableIRQ(SUBGHZ_Radio_IRQn); - irq_happened = true; -} - -int stm32wl_emulate_digitalRead(long unsigned int pin) -{ - int outcome = 0; - - switch (pin) { - case SX126X_BUSY: - // return ((LL_PWR_IsActiveFlag_RFBUSYMS() & LL_PWR_IsActiveFlag_RFBUSYS()) == 1UL); - outcome = LL_PWR_IsActiveFlag_RFBUSYS(); - break; - case SX126X_DIO1: - default: - NVIC_ClearPendingIRQ(SUBGHZ_Radio_IRQn); - irq_happened = false; - NVIC_EnableIRQ(SUBGHZ_Radio_IRQn); - for (int i = 0; i < 64; i++) - asm("nop"); - outcome = irq_happened; - break; - } - return outcome; -} diff --git a/src/platform/stm32wl/main-stm32wl.cpp b/src/platform/stm32wl/main-stm32wl.cpp index 8ebcb029e..f57928c60 100644 --- a/src/platform/stm32wl/main-stm32wl.cpp +++ b/src/platform/stm32wl/main-stm32wl.cpp @@ -11,8 +11,18 @@ void updateBatteryLevel(uint8_t level) {} void getMacAddr(uint8_t *dmac) { - for (int i = 0; i < 6; i++) - dmac[i] = i; + // https://flit.github.io/2020/06/06/mcu-unique-id-survey.html + const uint32_t uid0 = HAL_GetUIDw0(); // X/Y coordinate on wafer + const uint32_t uid1 = HAL_GetUIDw1(); // [31:8] Lot number (23:0), [7:0] Wafer number + const uint32_t uid2 = HAL_GetUIDw2(); // Lot number (55:24) + + // Need to go from 96-bit to 48-bit unique ID + dmac[5] = (uint8_t)uid0; + dmac[4] = (uint8_t)(uid0 >> 16); + dmac[3] = (uint8_t)uid1; + dmac[2] = (uint8_t)(uid1 >> 8); + dmac[1] = (uint8_t)uid2; + dmac[0] = (uint8_t)(uid2 >> 8); } void cpuDeepSleep(uint32_t msecToWake) {} diff --git a/src/power.h b/src/power.h index c47e78466..e90e3f21b 100644 --- a/src/power.h +++ b/src/power.h @@ -22,6 +22,13 @@ extern RTC_NOINIT_ATTR uint64_t RTC_reg_b; #include "soc/sens_reg.h" // needed for adc pin reset #endif +#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) +#include "modules/Telemetry/Sensor/INA219Sensor.h" +#include "modules/Telemetry/Sensor/INA260Sensor.h" +extern INA260Sensor ina260Sensor; +extern INA219Sensor ina219Sensor; +#endif + class Power : private concurrency::OSThread { @@ -41,7 +48,6 @@ class Power : private concurrency::OSThread /// Setup a xpowers chip axp192/axp2101, return true if found bool axpChipInit(); - /// Setup a simple ADC input based battery sensor bool analogInit(); diff --git a/src/shutdown.h b/src/shutdown.h index b08478a1e..ee63422dd 100644 --- a/src/shutdown.h +++ b/src/shutdown.h @@ -26,8 +26,8 @@ void powerCommandsCheck() if (shutdownAtMsec && millis() > shutdownAtMsec) { LOG_INFO("Shutting down from admin command\n"); - playShutdownMelody(); #if defined(ARCH_NRF52) || defined(ARCH_ESP32) + playShutdownMelody(); power->shutdown(); #else LOG_WARN("FIXME implement shutdown for this platform"); diff --git a/src/sleep.cpp b/src/sleep.cpp index 6dcf385b7..5331eaf75 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -103,13 +103,13 @@ void setGPSPower(bool on) if (pmu_found && PMU) { uint8_t model = PMU->getChipModel(); if (model == XPOWERS_AXP2101) { -#if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) - // t-beam v1.2 GNSS power channel - on ? PMU->enablePowerOutput(XPOWERS_ALDO3) : PMU->disablePowerOutput(XPOWERS_ALDO3); -#elif (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) - // t-beam-s3-core GNSS power channel - on ? PMU->enablePowerOutput(XPOWERS_ALDO4) : PMU->disablePowerOutput(XPOWERS_ALDO4); -#endif + if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) { + // t-beam v1.2 GNSS power channel + on ? PMU->enablePowerOutput(XPOWERS_ALDO3) : PMU->disablePowerOutput(XPOWERS_ALDO3); + } else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) { + // t-beam-s3-core GNSS power channel + on ? PMU->enablePowerOutput(XPOWERS_ALDO4) : PMU->disablePowerOutput(XPOWERS_ALDO4); + } } else if (model == XPOWERS_AXP192) { // t-beam v1.1 GNSS power channel on ? PMU->enablePowerOutput(XPOWERS_LDO3) : PMU->disablePowerOutput(XPOWERS_LDO3); @@ -252,12 +252,12 @@ void doDeepSleep(uint32_t msecToWake) uint8_t model = PMU->getChipModel(); if (model == XPOWERS_AXP2101) { -#if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) - // t-beam v1.2 radio power channel - PMU->disablePowerOutput(XPOWERS_ALDO2); // lora radio power channel -#elif (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) - PMU->disablePowerOutput(XPOWERS_ALDO3); // lora radio power channel -#endif + if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) { + // t-beam v1.2 radio power channel + PMU->disablePowerOutput(XPOWERS_ALDO2); // lora radio power channel + } else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) { + PMU->disablePowerOutput(XPOWERS_ALDO3); // lora radio power channel + } } else if (model == XPOWERS_AXP192) { // t-beam v1.1 radio power channel PMU->disablePowerOutput(XPOWERS_LDO2); // lora radio power channel diff --git a/src/xmodem.h b/src/xmodem.h index 848e926bd..2ba0bb39f 100644 --- a/src/xmodem.h +++ b/src/xmodem.h @@ -59,7 +59,7 @@ class XModemAdapter uint16_t packetno = 0; -#if defined(ARCH_NRF52) +#if defined(ARCH_NRF52) || defined(ARCH_STM32WL) File file = File(FSCom); #else File file; diff --git a/suppressions.txt b/suppressions.txt index 0dd5198ec..e2af9aeef 100644 --- a/suppressions.txt +++ b/suppressions.txt @@ -36,6 +36,7 @@ cstyleCast // ignore stuff that is not ours *:.pio/* *:*/libdeps/* +*:*/generated/* noExplicitConstructor:*/mqtt/* postfixOperator:*/mqtt/* @@ -44,3 +45,5 @@ missingOverride virtualCallInConstructor passedByValue:*/RedirectablePrint.h + +internalAstError:*/CrossPlatformCryptoEngine.cpp diff --git a/variants/heltec_v3/variant.h b/variants/heltec_v3/variant.h index 16ee6d712..d9fc0b4c2 100644 --- a/variants/heltec_v3/variant.h +++ b/variants/heltec_v3/variant.h @@ -9,6 +9,7 @@ #define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage #define ADC_CHANNEL ADC1_GPIO1_CHANNEL +#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider #define ADC_MULTIPLIER 4.9 #define USE_SX1262 diff --git a/variants/heltec_wsl_v3/variant.h b/variants/heltec_wsl_v3/variant.h index 38b38e759..0ecc5bea7 100644 --- a/variants/heltec_wsl_v3/variant.h +++ b/variants/heltec_wsl_v3/variant.h @@ -10,6 +10,7 @@ #define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage #define ADC_CHANNEL ADC1_GPIO1_CHANNEL +#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider #define ADC_MULTIPLIER 4.9 #define USE_SX1262 diff --git a/variants/rak11310/pins_arduino.h b/variants/rak11310/pins_arduino.h new file mode 100644 index 000000000..626bed1da --- /dev/null +++ b/variants/rak11310/pins_arduino.h @@ -0,0 +1,68 @@ +#pragma once + +// Pin definitions taken from: +// https://datasheets.raspberrypi.org/pico/pico-datasheet.pdf + +static const uint8_t WB_IO1 = 6; // SLOT_A SLOT_B +static const uint8_t WB_IO2 = 22; // SLOT_A SLOT_B +static const uint8_t WB_IO3 = 7; // SLOT_C +static const uint8_t WB_IO4 = 28; // SLOT_C +static const uint8_t WB_IO5 = 9; // SLOT_D +static const uint8_t WB_IO6 = 8; // SLOT_D +static const uint8_t WB_A0 = 26; // IO_SLOT +static const uint8_t WB_A1 = 27; // IO_SLOT + +#define PIN_A0 (26u) +#define PIN_A1 (27u) +#define PIN_A2 (28u) +#define PIN_A3 (29u) + +static const uint8_t A0 = PIN_A0; +static const uint8_t A1 = PIN_A1; +static const uint8_t A2 = PIN_A2; +static const uint8_t A3 = PIN_A3; + +// LEDs +#define PIN_LED (23u) +#define PIN_LED1 PIN_LED +#define PIN_LED2 (24u) +#define LED_BUILTIN PIN_LED + +#define ADC_RESOLUTION 12 + +// Serial +#define PIN_SERIAL1_TX (0ul) +#define PIN_SERIAL1_RX (1ul) + +#define PIN_SERIAL2_TX (4ul) +#define PIN_SERIAL2_RX (5ul) + +// SPI +#define PIN_SPI0_MISO (12u) +#define PIN_SPI0_MOSI (11u) +#define PIN_SPI0_SCK (10u) +#define PIN_SPI0_SS (13u) + +#define PIN_SPI1_MISO (16u) +#define PIN_SPI1_MOSI (19u) +#define PIN_SPI1_SCK (18u) +#define PIN_SPI1_SS (17u) + +// Wire +#define PIN_WIRE0_SDA (2u) +#define PIN_WIRE0_SCL (3u) + +#define PIN_WIRE1_SDA (20u) +#define PIN_WIRE1_SCL (21u) + +#define SERIAL_HOWMANY (3u) +#define SPI_HOWMANY (2u) +#define WIRE_HOWMANY (2u) + +static const uint8_t SS = PIN_SPI0_SS; +static const uint8_t MOSI = PIN_SPI0_MOSI; +static const uint8_t MISO = PIN_SPI0_MISO; +static const uint8_t SCK = PIN_SPI0_SCK; + +static const uint8_t SDA = PIN_WIRE0_SDA; +static const uint8_t SCL = PIN_WIRE0_SCL; \ No newline at end of file diff --git a/variants/rak11310/platformio.ini b/variants/rak11310/platformio.ini new file mode 100644 index 000000000..a69b18c1a --- /dev/null +++ b/variants/rak11310/platformio.ini @@ -0,0 +1,13 @@ +[env:rak11310] +extends = rp2040_base +board = wiscore_rak11300 +upload_protocol = picotool + +# add our variants files to the include and src paths +build_flags = ${rp2040_base.build_flags} + -DRAK11310 + -Ivariants/rak11310 + -DDEBUG_RP2040_PORT=Serial + -L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m0plus" +lib_deps = + ${rp2040_base.lib_deps} \ No newline at end of file diff --git a/variants/rak11310/variant.h b/variants/rak11310/variant.h new file mode 100644 index 000000000..1d1577cfd --- /dev/null +++ b/variants/rak11310/variant.h @@ -0,0 +1,54 @@ +// #define RADIOLIB_CUSTOM_ARDUINO 1 +// #define RADIOLIB_TONE_UNSUPPORTED 1 +// #define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED 1 + +#define ARDUINO_ARCH_AVR + +#undef CBC +#define CBC 0 +#undef CTR +#define CTR 1 +#undef ECB +#define ECB 0 + +#undef GPS_SERIAL_NUM + +#define LED_CONN PIN_LED2 +#define LED_PIN LED_BUILTIN + +#define BUTTON_PIN 9 +#define BUTTON_NEED_PULLUP +// #define EXT_NOTIFY_OUT 4 + +#define BATTERY_PIN 26 +// ratio of voltage divider = 3.0 (R17=200k, R18=100k) +#define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic + +#define USE_SX1262 + +#undef RF95_SCK +#undef RF95_MISO +#undef RF95_MOSI +#undef RF95_NSS + +// RAK BSP somehow uses SPI1 instead of SPI0 +#define HW_SPI1_DEVICE +#define RF95_SCK PIN_SPI0_SCK +#define RF95_MOSI PIN_SPI0_MOSI +#define RF95_MISO PIN_SPI0_MISO +#define RF95_NSS PIN_SPI0_SS + +#define LORA_DIO0 RADIOLIB_NC +#define LORA_RESET 14 +#define LORA_DIO1 29 +#define LORA_DIO2 15 +#define LORA_DIO3 RADIOLIB_NC + +#ifdef USE_SX1262 +#define SX126X_CS RF95_NSS +#define SX126X_DIO1 LORA_DIO1 +#define SX126X_BUSY LORA_DIO2 +#define SX126X_RESET LORA_RESET +#define SX126X_POWER_EN 25 +#define SX126X_E22 // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3 +#endif \ No newline at end of file diff --git a/variants/rak4631/variant.h b/variants/rak4631/variant.h index 69a77a029..fe9f062c8 100644 --- a/variants/rak4631/variant.h +++ b/variants/rak4631/variant.h @@ -258,6 +258,7 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG #define PIN_ETHERNET_RESET 21 #define PIN_ETHERNET_SS PIN_EINK_CS #define ETH_SPI_PORT SPI1 +#define AQ_SET_PIN 10 #ifdef __cplusplus } @@ -267,4 +268,4 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG * Arduino objects - C++ only *----------------------------------------------------------------------------*/ -#endif +#endif \ No newline at end of file diff --git a/variants/rpipico/platformio.ini b/variants/rpipico/platformio.ini index a169e8a9d..727a1cab6 100644 --- a/variants/rpipico/platformio.ini +++ b/variants/rpipico/platformio.ini @@ -1,18 +1,14 @@ [env:pico] extends = rp2040_base board = rpipico -board_level = extra upload_protocol = picotool # add our variants files to the include and src paths build_flags = ${rp2040_base.build_flags} - -DPRIVATE_HW + -DRPI_PICO -Ivariants/rpipico - -DARDUINO_AVR_NANO_EVERY - -DDEBUG_RP2040_WIRE - -DDEBUG_RP2040_SPI - -DDEBUG_RP2040_CORE -DDEBUG_RP2040_PORT=Serial - -DUSE_TINYUSB + -DHW_SPI1_DEVICE + -L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m0plus" lib_deps = ${rp2040_base.lib_deps} \ No newline at end of file diff --git a/variants/rpipico/variant.h b/variants/rpipico/variant.h index d620a356b..7e2660aa6 100644 --- a/variants/rpipico/variant.h +++ b/variants/rpipico/variant.h @@ -4,8 +4,11 @@ #define ARDUINO_ARCH_AVR +#undef CBC #define CBC 0 +#undef CTR #define CTR 1 +#undef ECB #define ECB 0 #define NO_GPS 1 @@ -18,11 +21,12 @@ #define BUTTON_PIN 17 #define EXT_NOTIFY_OUT 4 +#define LED_PIN PIN_LED + #define BATTERY_PIN 26 // ratio of voltage divider = 3.0 (R17=200k, R18=100k) #define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic -#define USE_RF95 #define USE_SX1262 #undef RF95_SCK @@ -47,6 +51,4 @@ #define SX126X_BUSY LORA_DIO2 #define SX126X_RESET LORA_RESET #define SX126X_E22 -#endif - -#include \ No newline at end of file +#endif \ No newline at end of file diff --git a/variants/rpipicow/platformio.ini b/variants/rpipicow/platformio.ini index 6e5c32a52..3228e4c24 100644 --- a/variants/rpipicow/platformio.ini +++ b/variants/rpipicow/platformio.ini @@ -6,13 +6,10 @@ upload_protocol = picotool # add our variants files to the include and src paths build_flags = ${rp2040_base.build_flags} - -DPRIVATE_HW + -DRPI_PICO -Ivariants/rpipicow - -DARDUINO_AVR_NANO_EVERY - -DDEBUG_RP2040_WIRE - -DDEBUG_RP2040_SPI - -DDEBUG_RP2040_CORE -DDEBUG_RP2040_PORT=Serial - -DUSE_TINYUSB + -DHW_SPI1_DEVICE + -L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m0plus" lib_deps = ${rp2040_base.lib_deps} \ No newline at end of file diff --git a/variants/rpipicow/variant.h b/variants/rpipicow/variant.h index d620a356b..4741fd130 100644 --- a/variants/rpipicow/variant.h +++ b/variants/rpipicow/variant.h @@ -4,8 +4,11 @@ #define ARDUINO_ARCH_AVR +#undef CBC #define CBC 0 +#undef CTR #define CTR 1 +#undef ECB #define ECB 0 #define NO_GPS 1 @@ -22,7 +25,6 @@ // ratio of voltage divider = 3.0 (R17=200k, R18=100k) #define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic -#define USE_RF95 #define USE_SX1262 #undef RF95_SCK @@ -47,6 +49,4 @@ #define SX126X_BUSY LORA_DIO2 #define SX126X_RESET LORA_RESET #define SX126X_E22 -#endif - -#include \ No newline at end of file +#endif \ No newline at end of file diff --git a/variants/wio-e5/platformio.ini b/variants/wio-e5/platformio.ini index 32436dae8..07f6efa6d 100644 --- a/variants/wio-e5/platformio.ini +++ b/variants/wio-e5/platformio.ini @@ -1,5 +1,11 @@ [env:wio-e5] extends = stm32wl5e_base board_level = extra -build_flags = ${stm32wl5e_base.build_flags} -Ivariants/wio-e5 -DHAL_DAC_MODULE_ONLY - -DSERIAL_UART_INSTANCE=1 -DPIN_SERIAL_RX=PB7 -DPIN_SERIAL_TX=PB6 +build_flags = + ${stm32wl5e_base.build_flags} + -Ivariants/wio-e5 + -DHAL_DAC_MODULE_ONLY + -DSERIAL_UART_INSTANCE=1 + -DPIN_SERIAL_RX=PB7 + -DPIN_SERIAL_TX=PB6 +upload_port = stlink \ No newline at end of file diff --git a/variants/wio-e5/variant.h b/variants/wio-e5/variant.h index b1f7556b4..86e58bcb2 100644 --- a/variants/wio-e5/variant.h +++ b/variants/wio-e5/variant.h @@ -12,18 +12,6 @@ Do not expect a working Meshtastic device with this target. #ifndef _VARIANT_WIOE5_ #define _VARIANT_WIOE5_ -// Arduino/PlatformIO support for SUBGHZSPI is not currently available -//#define USE_SX1262 - -#ifdef USE_SX1262 -#define HAS_RADIO 1 - -/* module only transmits through RFO_HP */ -#define SX126X_RXEN PA5 -#define SX126X_TXEN PA4 - -/* TCXO fed by internal LDO option behind PB0 pin */ -#define SX126X_E22 -#endif +#define USE_STM32WLx #endif \ No newline at end of file diff --git a/version.properties b/version.properties index 32b1f1a72..1b9a7da4f 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 1 -build = 13 +build = 17