diff --git a/.github/ISSUE_TEMPLATE/Bug Report.yml b/.github/ISSUE_TEMPLATE/Bug Report.yml index 795c1b1a09..d4e00b4eda 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 9ef8f77c65..32f280a045 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 6194bfe692..caf04fff65 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 @@ -186,7 +188,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 be3ca33974..89f8ee065e 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 42d55613c3..8805b0716c 100644 --- a/arch/esp32/esp32.ini +++ b/arch/esp32/esp32.ini @@ -1,7 +1,7 @@ ; Common settings for ESP targes, mixin with extends = esp32_base [esp32_base] extends = arduino_base -platform = platformio/espressif32@^6.1.0 +platform = platformio/espressif32@^6.2.0 build_src_filter = ${arduino_base.build_src_filter} - - - - - diff --git a/arch/nrf52/nrf52.ini b/arch/nrf52/nrf52.ini index 0da344199d..7b5e04abbb 100644 --- a/arch/nrf52/nrf52.ini +++ b/arch/nrf52/nrf52.ini @@ -1,6 +1,6 @@ [nrf52_base] ; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files -platform = platformio/nordicnrf52@^9.5.0 +platform = platformio/nordicnrf52@^9.6.0 extends = arduino_base build_type = debug ; I'm debugging with ICE a lot now diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index 9a3156ba83..d23ed886f2 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -1,6 +1,6 @@ ; The Portduino based sim environment on top of any host OS, all hardware will be simulated [portduino_base] -platform = https://github.com/meshtastic/platform-native.git#096b3c3e9c5c8e19d4c3b6cd803fffef2a9be4c5 +platform = https://github.com/meshtastic/platform-native.git#489ff929dca0bb768256ba2de45f95815111490f framework = arduino build_src_filter = @@ -28,4 +28,4 @@ lib_deps = 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 77dbfdbc01..5b01367686 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.1 board_build.core = earlephilhower board_build.filesystem_size = 0.5m @@ -20,4 +21,4 @@ lib_deps = ${arduino_base.lib_deps} ${environmental_base.lib_deps} jgromes/RadioLib@^6.0.0 - https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b + 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 7f4a008cee..5a5edcde39 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 = ${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} - - - - - - - - - - - - - - - +board_upload.offset_address = 0x08000000 +upload_protocol = stlink + lib_deps = ${env.lib_deps} jgromes/RadioLib@^6.0.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 = - mathertel/OneButton@^2.0.3 +lib_ignore = + https://github.com/mathertel/OneButton#2.1.0 diff --git a/boards/generic_wl5e.json b/boards/generic_wl5e.json index 433c55b594..5c4bc24a75 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 0000000000..19beee74dd --- /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 2040b75ce6..9abb56b7ae 100644 --- a/platformio.ini +++ b/platformio.ini @@ -2,17 +2,17 @@ ; 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 ;default_envs = heltec-v1 -;default_envs = heltec-v2.0 -;default_envs = heltec-v2.1 +;default_envs = heltec-v2_0 +;default_envs = heltec-v2_1 ;default_envs = tlora-v1 ;default_envs = tlora_v1_3 ;default_envs = tlora-v2 -;default_envs = tlora-v2-1-1.6 +;default_envs = tlora-v2-1-1_6 ;default_envs = tlora-t3s3-v1 ;default_envs = lora-relay-v1 # nrf board ;default_envs = t-echo @@ -21,17 +21,18 @@ default_envs = tbeam ;default_envs = nano-g1 ;default_envs = pca10059_diy_eink ;default_envs = meshtastic-diy-v1 -;default_envs = meshtastic-diy-v1.1 +;default_envs = meshtastic-diy-v1_1 ;default_envs = meshtastic-dr-dev ;default_envs = m5stack-coreink ;default_envs = rak4631 +default_envs = wio-e5 extra_configs = arch/*/*.ini variants/*/platformio.ini [env] -extra_scripts = bin/platformio-custom.py +extra_scripts = bin/platformio-custom.py ; note: we add src to our include search path so that lmic_project_config can override ; note: TINYGPS_OPTION_NO_CUSTOM_FIELDS is VERY important. We don't use custom fields and somewhere in that pile @@ -39,8 +40,8 @@ extra_scripts = bin/platformio-custom.py ; FIXME: fix lib/BluetoothOTA dependency back on src/ so we can remove -Isrc ; The Radiolib stuff will speed up building considerably. Exclud all the stuff we dont need. build_flags = -Wno-missing-field-initializers - -Wno-format - -Isrc -Isrc/mesh -Isrc/mesh/generated -Isrc/gps -Isrc/buzz -Wl,-Map,.pio/build/output.map + -Wno-format + -Isrc -Isrc/mesh -Isrc/mesh/generated -Isrc/gps -Isrc/buzz -Wl,-Map,.pio/build/output.map -DUSE_THREAD_NAMES -DTINYGPS_OPTION_NO_CUSTOM_FIELDS -DPB_ENABLE_MALLOC=1 @@ -59,8 +60,8 @@ build_flags = -Wno-missing-field-initializers monitor_speed = 115200 lib_deps = - https://github.com/meshtastic/esp8266-oled-ssd1306.git#b38094e03dfa964fbc0e799bc374e91a605c1223 ; ESP8266_SSD1306 - mathertel/OneButton@^2.0.3 ; OneButton library for non-blocking button debounce + https://github.com/meshtastic/esp8266-oled-ssd1306.git#b38094e03dfa964fbc0e799bc374e91a605c1223 ; ESP8266_SSD1306 + https://github.com/mathertel/OneButton#2.1.0 ; OneButton library for non-blocking button debounce https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159 https://github.com/meshtastic/TinyGPSPlus.git#127ad674ef85f0201cb68a065879653ed94792c4 https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3 @@ -87,14 +88,14 @@ lib_deps = build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0 build_src_filter = ${env.build_src_filter} - -; Common libs for communicating over TCP/IP networks such as MQTT +; Common libs for communicating over TCP/IP networks such as MQTT [networking_base] lib_deps = knolleary/PubSubClient@^2.8 arduino-libraries/NTPClient@^3.1.0 arcao/Syslog@^2.0.0 -; Common libs for environmental measurements in telemetry module +; Common libs for environmental measurements in telemetry module ; (not included in native / portduino) [environmental_base] lib_deps = @@ -102,7 +103,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 @@ -112,4 +113,4 @@ lib_deps = adafruit/Adafruit SHT31 Library@^2.2.0 adafruit/Adafruit PM25 AQI Sensor@^1.0.6 adafruit/Adafruit MPU6050@^2.2.4 - adafruit/Adafruit LIS3DH@^1.2.4 + adafruit/Adafruit LIS3DH@^1.2.4 \ No newline at end of file diff --git a/protobufs b/protobufs index e84f0cc7ca..5f3daac5fa 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit e84f0cc7cab2879b00085000589b9fd6527d0d68 +Subproject commit 5f3daac5fabdfe2a0561395fed0ba11a38ba3e7e diff --git a/src/ButtonThread.h b/src/ButtonThread.h index 0a8b2afa58..173566f938 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.refreshLocalNodeInfo(); service.sendNetworkPing(NODENUM_BROADCAST, true); } diff --git a/src/DebugConfiguration.h b/src/DebugConfiguration.h index 36b009ff2a..59ce043bcb 100644 --- a/src/DebugConfiguration.h +++ b/src/DebugConfiguration.h @@ -28,6 +28,7 @@ #define DEBUG_PORT (*console) // Serial debug port #ifdef USE_SEGGER +#define DEBUG_PORT #define LOG_DEBUG(...) SEGGER_RTT_printf(0, __VA_ARGS__) #define LOG_INFO(...) SEGGER_RTT_printf(0, __VA_ARGS__) #define LOG_WARN(...) SEGGER_RTT_printf(0, __VA_ARGS__) diff --git a/src/FSCommon.cpp b/src/FSCommon.cpp index cc99caed80..150391237b 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 98d3911d77..ef1d3e4c17 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 bdfce36ff4..6b760385fc 100644 --- a/src/GPSStatus.h +++ b/src/GPSStatus.h @@ -138,8 +138,9 @@ class GPSStatus : public Status LOG_DEBUG("New GPS pos@%x:3 lat=%f, lon=%f, alt=%d, pdop=%.2f, track=%.2f, speed=%.2f, sats=%d\n", p.timestamp, p.latitude_i * 1e-7, p.longitude_i * 1e-7, p.altitude, p.PDOP * 1e-2, p.ground_track * 1e-5, p.ground_speed * 1e-2, p.sats_in_view); - } else + } else { LOG_DEBUG("No GPS lock\n"); + } onNewStatus.notifyObservers(this); } return 0; diff --git a/src/Power.cpp b/src/Power.cpp index b129fbcd09..37d80a31f1 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -17,12 +17,38 @@ #define DELAY_FOREVER portMAX_DELAY #endif +#if defined(BATTERY_PIN) && defined(ARCH_ESP32) + +#ifndef BAT_MEASURE_ADC_UNIT // ADC1 is default +static const adc1_channel_t adc_channel = ADC_CHANNEL; +static const adc_unit_t unit = ADC_UNIT_1; +#else // ADC2 +static const adc2_channel_t adc_channel = ADC_CHANNEL; +static const adc_unit_t unit = ADC_UNIT_2; +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 @@ -108,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 @@ -128,18 +161,41 @@ class AnalogBatteryLevel : public HasBatteryLevel // Set the number of samples, it has an effect of increasing sensitivity, especially in complex electromagnetic // environment. uint32_t raw = 0; +#ifdef ARCH_ESP32 +#ifndef BAT_MEASURE_ADC_UNIT // ADC1 + for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) { + raw += adc1_get_raw(adc_channel); + } +#else // ADC2 + int32_t adc_buf = 0; + for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) { + // ADC2 wifi bug workaround, see + // https://github.com/espressif/arduino-esp32/issues/102 + WRITE_PERI_REG(SENS_SAR_READ_CTRL2_REG, RTC_reg_b); + SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DATA_INV); + adc2_get_raw(adc_channel, ADC_WIDTH_BIT_12, &adc_buf); + raw += adc_buf; + } +#endif // BAT_MEASURE_ADC_UNIT +#else // !ARCH_ESP32 for (uint32_t i = 0; i < BATTERY_SENSE_SAMPLES; i++) { raw += analogRead(BATTERY_PIN); } +#endif raw = raw / BATTERY_SENSE_SAMPLES; - float scaled; +#ifdef ARCH_ESP32 + scaled = esp_adc_cal_raw_to_voltage(raw, adc_characs); + scaled *= operativeAdcMultiplier; +#else #ifndef VBAT_RAW_TO_SCALED scaled = 1000.0 * operativeAdcMultiplier * (AREF_VOLTAGE / 1024.0) * raw; #else scaled = VBAT_RAW_TO_SCALED(raw); // defined in variant.h -#endif - // LOG_DEBUG("battery gpio %d raw val=%u scaled=%u\n", BATTERY_PIN, raw, (uint32_t)(scaled)); +#endif // VBAT RAW TO SCALED +#endif // ARCH_ESP32 + // LOG_DEBUG("battery gpio %d raw val=%u scaled=%u\n", BATTERY_PIN, raw, (uint32_t)(scaled)); + last_read_value = scaled; return scaled; } else { @@ -147,7 +203,7 @@ class AnalogBatteryLevel : public HasBatteryLevel } #else return 0; -#endif +#endif // BATTERY_PIN } /** @@ -203,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; @@ -228,25 +313,52 @@ bool Power::analogInit() // disable any internal pullups pinMode(BATTERY_PIN, INPUT); -#ifdef ARCH_ESP32 - // ESP32 needs special analog stuff - adcAttachPin(BATTERY_PIN); +#ifndef BATTERY_SENSE_RESOLUTION_BITS +#define BATTERY_SENSE_RESOLUTION_BITS 10 +#endif + +#ifdef ARCH_ESP32 // ESP32 needs special analog stuff + +#ifndef ADC_WIDTH // max resolution by default + static const adc_bits_width_t width = ADC_WIDTH_BIT_12; +#else + static const adc_bits_width_t width = ADC_WIDTH; +#endif +#ifndef BAT_MEASURE_ADC_UNIT // ADC1 + adc1_config_width(width); + adc1_config_channel_atten(adc_channel, atten); +#else // ADC2 + adc2_config_channel_atten(adc_channel, atten); + // ADC2 wifi bug workaround + RTC_reg_b = READ_PERI_REG(SENS_SAR_READ_CTRL2_REG); +#endif + // calibrate ADC + 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) { + LOG_INFO("ADCmod: ADC characterization based on Two Point values stored in eFuse\n"); + } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) { + LOG_INFO("ADCmod: ADC characterization based on reference voltage stored in eFuse\n"); + } else { + 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 #ifdef VBAT_AR_INTERNAL analogReference(VBAT_AR_INTERNAL); #else analogReference(AR_INTERNAL); // 3.6V #endif -#endif - -#ifndef BATTERY_SENSE_RESOLUTION_BITS -#define BATTERY_SENSE_RESOLUTION_BITS 10 -#endif - - // adcStart(BATTERY_PIN); analogReadResolution(BATTERY_SENSE_RESOLUTION_BITS); // Default of 12 is not very linear. Recommended to use 10 or 11 // depending on needed resolution. + +#endif // ARCH_NRF52 + batteryLevel = &analogLevel; return true; #else @@ -302,7 +414,7 @@ void Power::readPowerStatus() { if (batteryLevel) { bool hasBattery = batteryLevel->isBatteryConnect(); - int batteryVoltageMv = 0; + uint32_t batteryVoltageMv = 0; int8_t batteryChargePercent = 0; if (hasBattery) { batteryVoltageMv = batteryLevel->getBattVoltage(); @@ -365,8 +477,8 @@ void Power::readPowerStatus() #endif - // If we have a battery at all and it is less than 10% full, force deep sleep if we have more than 10 low readings in a - // row + // If we have a battery at all and it is less than 10% full, force deep sleep if we have more than 10 low readings in + // a row if (powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) { if (batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS) { low_voltage_counter++; @@ -444,10 +556,10 @@ int32_t Power::runOnce() * Init the power manager chip * * axp192 power - DCDC1 0.7-3.5V @ 1200mA max -> OLED // If you turn this off you'll lose comms to the axp192 because the OLED and the axp192 - share the same i2c bus, instead use ssd1306 sleep mode DCDC2 -> unused DCDC3 0.7-3.5V @ 700mA max -> ESP32 (keep this on!) LDO1 - 30mA -> charges GPS backup battery // charges the tiny J13 battery by the GPS to power the GPS ram (for a couple of days), can - not be turned off LDO2 200mA -> LORA LDO3 200mA -> GPS + DCDC1 0.7-3.5V @ 1200mA max -> OLED // If you turn this off you'll lose comms to the axp192 because the OLED and the + axp192 share the same i2c bus, instead use ssd1306 sleep mode DCDC2 -> unused DCDC3 0.7-3.5V @ 700mA max -> ESP32 (keep this + on!) LDO1 30mA -> charges GPS backup battery // charges the tiny J13 battery by the GPS to power the GPS ram (for a couple of + days), can not be turned off LDO2 200mA -> LORA LDO3 200mA -> GPS * */ bool Power::axpChipInit() @@ -540,81 +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); - - // 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); - - // LoRa VDD 3300mV - PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); - PMU->enablePowerOutput(XPOWERS_ALDO2); - - // GNSS VDD 3300mV - PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); - PMU->enablePowerOutput(XPOWERS_ALDO3); - -#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); - - // 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); - - // 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); - - // 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 + 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); + + // 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); + + // 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); + + // 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); + + /** + * 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); + + // sdcard power channle + PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300); + PMU->enablePowerOutput(XPOWERS_BLDO1); + + // 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); + } // disable all axp chip interrupt PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ); diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 6804242c23..e2cf942582 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 39ea76c007..0e8e1c798a 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 91b4e2826c..e827dcf3b9 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 7be4c5b0dc..2702ee2bf6 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/concurrency/NotifiedWorkerThread.cpp b/src/concurrency/NotifiedWorkerThread.cpp index 39a594c5a2..271e3e60d5 100644 --- a/src/concurrency/NotifiedWorkerThread.cpp +++ b/src/concurrency/NotifiedWorkerThread.cpp @@ -31,12 +31,14 @@ IRAM_ATTR bool NotifiedWorkerThread::notifyCommon(uint32_t v, bool overwrite) runASAP = true; notification = v; - if (debugNotification) + if (debugNotification) { LOG_DEBUG("setting notification %d\n", v); + } return true; } else { - if (debugNotification) + if (debugNotification) { LOG_DEBUG("dropping notification %d\n", v); + } return false; } } @@ -64,8 +66,9 @@ bool NotifiedWorkerThread::notifyLater(uint32_t delay, uint32_t v, bool overwrit if (didIt) { // If we didn't already have something queued, override the delay to be larger setIntervalFromNow(delay); // a new version of setInterval relative to the current time - if (debugNotification) + if (debugNotification) { LOG_DEBUG("delaying notification %u\n", delay); + } } return didIt; diff --git a/src/concurrency/OSThread.cpp b/src/concurrency/OSThread.cpp index c71d3510eb..f23cbe1dce 100644 --- a/src/concurrency/OSThread.cpp +++ b/src/concurrency/OSThread.cpp @@ -61,14 +61,17 @@ bool OSThread::shouldRun(unsigned long time) { bool r = Thread::shouldRun(time); - if (showRun && r) + if (showRun && r) { LOG_DEBUG("Thread %s: run\n", ThreadName.c_str()); + } - if (showWaiting && enabled && !r) + if (showWaiting && enabled && !r) { LOG_DEBUG("Thread %s: wait %lu\n", ThreadName.c_str(), interval); + } - if (showDisabled && !enabled) + if (showDisabled && !enabled) { LOG_DEBUG("Thread %s: disabled\n", ThreadName.c_str()); + } return r; } diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index b7f16734f0..7afb03ee25 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 fc0707cd6e..d16ee6595f 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 c5dfddc8e9..dbe7c40014 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) #define HAS_FREE_RTOS #include diff --git a/src/gps/NMEAWPL.cpp b/src/gps/NMEAWPL.cpp index ac11d78f8c..784ecac5d6 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_Position &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); diff --git a/src/gps/NMEAWPL.h b/src/gps/NMEAWPL.h index a9f00cb140..d597b7ea68 100644 --- a/src/gps/NMEAWPL.h +++ b/src/gps/NMEAWPL.h @@ -3,5 +3,5 @@ #include "main.h" #include -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_Position &pos, const char *name, bool isCaltopoMode = false); uint32_t printGGA(char *buf, size_t bufsz, const meshtastic_Position &pos); diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 2192140915..6b72a5d7d3 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); @@ -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; @@ -856,12 +850,12 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ } bool hasNodeHeading = false; - if (ourNode && hasPosition(ourNode)) { + if (ourNode && hasValidPosition(ourNode)) { meshtastic_Position &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; @@ -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); @@ -1239,8 +1234,10 @@ void Screen::setFrames() moduleFrames = MeshModule::GetMeshModulesWithUIFrames(); LOG_DEBUG("Showing %d module frames\n", moduleFrames.size()); +#ifdef DEBUG_PORT int totalFrameCount = MAX_NUM_NODES + NUM_EXTRA_FRAMES + moduleFrames.size(); LOG_DEBUG("Total frame count: %d\n", totalFrameCount); +#endif // We don't show the node info our our node (if we have it yet - we should) size_t numnodes = nodeDB.getNumNodes(); @@ -1262,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 diff --git a/src/main.cpp b/src/main.cpp index 324422a692..937f9091a6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,6 +59,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 +71,7 @@ NRF52Bluetooth *nrf52Bluetooth; #endif #include "PowerFSMThread.h" -#if !defined(ARCH_PORTDUINO) +#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) #include "AccelerometerThread.h" #endif @@ -260,6 +263,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 +356,11 @@ 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) +#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 +449,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 +457,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 @@ -462,10 +486,11 @@ void setup() gps = createGps(); - if (gps) + if (gps) { gpsStatus->observe(&gps->newStatus); - else + } else { LOG_WARN("No GPS found - running without GPS\n"); + } nodeStatus->observe(&nodeDB.newStatus); @@ -508,11 +533,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) { @@ -634,12 +673,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 @@ -660,7 +697,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; @@ -669,6 +706,7 @@ extern meshtastic_DeviceMetadata getDeviceMetadata() deviceMetadata.role = config.device.role; deviceMetadata.position_flags = config.position.position_flags; deviceMetadata.hw_model = HW_VENDOR; + deviceMetadata.hasRemoteHardware = moduleConfig.remote_hardware.enabled; return deviceMetadata; } @@ -716,4 +754,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 0d23dd10c8..93baec590b 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/Channels.cpp b/src/mesh/Channels.cpp index 5e2cb41ba5..2a0b5ee396 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -108,8 +108,9 @@ CryptoKey Channels::getKey(ChannelIndex chIndex) if (ch.role == meshtastic_Channel_Role_SECONDARY) { LOG_DEBUG("Unset PSK for secondary channel %s. using primary key\n", ch.settings.name); k = getKey(primaryIndex); - } else + } else { LOG_WARN("User disabled encryption\n"); + } } else if (k.length == 1) { // Convert the short single byte variants of psk into variant that can be used more generally diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index d8861943e3..1711992778 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 73b0bdfbc2..c732829e94 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/MeshModule.cpp b/src/mesh/MeshModule.cpp index d8dbf8a3a5..55948b33fa 100644 --- a/src/mesh/MeshModule.cpp +++ b/src/mesh/MeshModule.cpp @@ -179,9 +179,10 @@ void MeshModule::callPlugins(const meshtastic_MeshPacket &mp, RxSource src) } } - if (!moduleFound) + if (!moduleFound) { LOG_DEBUG("No modules interested in portnum=%d, src=%s\n", mp.decoded.portnum, (src == RX_SRC_LOCAL) ? "LOCAL" : "REMOTE"); + } } meshtastic_MeshPacket *MeshModule::allocReply() diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index 3b9ae26d24..06d30db4e8 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -239,7 +239,7 @@ void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies) meshtastic_NodeInfo *node = nodeDB.getNode(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,7 +266,7 @@ void MeshService::sendToPhone(meshtastic_MeshPacket *p) fromNum++; } -meshtastic_NodeInfo *MeshService::refreshMyNodeInfo() +meshtastic_NodeInfo *MeshService::refreshLocalNodeInfo() { meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); assert(node); @@ -293,7 +293,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_NodeInfo *node = refreshLocalNodeInfo(); meshtastic_Position pos = meshtastic_Position_init_default; if (newStatus->getHasLock()) { @@ -312,7 +312,7 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus) } // 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 refreshLocalNodeInfo() above, but these are // inexpensive nonblocking calls and can be refactored in due course pos.time = getValidTime(RTCQualityGPS); diff --git a/src/mesh/MeshService.h b/src/mesh/MeshService.h index 4314ea3621..96878492be 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_NodeInfo *refreshLocalNodeInfo(); /// Send a packet to the phone void sendToPhone(meshtastic_MeshPacket *p); diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 5ee839b803..a18d0a7b4d 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -56,6 +56,10 @@ extern void getMacAddr(uint8_t *dmac); */ meshtastic_User &owner = devicestate.owner; +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) {} @@ -275,9 +279,6 @@ void NodeDB::installDefaultDeviceState() 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 @@ -289,7 +290,6 @@ void NodeDB::installDefaultDeviceState() snprintf(owner.short_name, sizeof(owner.short_name), "%02x%02x", ourMacAddr[4], ourMacAddr[5]); snprintf(owner.id, sizeof(owner.id), "!%08x", getNodeNum()); // Default node ID now based on nodenum - memcpy(owner.macaddr, ourMacAddr, sizeof(owner.macaddr)); } void NodeDB::init() @@ -303,17 +303,12 @@ 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 @@ -324,19 +319,12 @@ void NodeDB::init() info->user = owner; info->has_user = true; - strncpy(myNodeInfo.firmware_version, optstr(APP_VERSION), sizeof(myNodeInfo.firmware_version)); - #ifdef ARCH_ESP32 Preferences preferences; preferences.begin("meshtastic", false); 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 @@ -349,6 +337,11 @@ void NodeDB::init() if (channelFileCRC != crc32Buffer(&channelFile, sizeof(channelFile))) saveWhat |= SEGMENT_CHANNELS; + if (!devicestate.node_remote_hardware_pins) { + meshtastic_NodeRemoteHardwarePin empty[12] = {meshtastic_RemoteHardwarePin_init_default}; + memcpy(devicestate.node_remote_hardware_pins, empty, sizeof(empty)); + } + saveToDisk(saveWhat); } @@ -468,8 +461,9 @@ void NodeDB::loadFromDisk() } } - if (loadProto(oemConfigFile, meshtastic_OEMStore_size, sizeof(meshtastic_OEMStore), &meshtastic_OEMStore_msg, &oemStore)) + if (loadProto(oemConfigFile, meshtastic_OEMStore_size, sizeof(meshtastic_OEMStore), &meshtastic_OEMStore_msg, &oemStore)) { LOG_INFO("Loaded OEMStore\n"); + } } /** Save a protobuf from a file, return true for success */ @@ -494,10 +488,12 @@ bool NodeDB::saveProto(const char *filename, size_t protoSize, const pb_msgdesc_ f.close(); // brief window of risk here ;-) - if (FSCom.exists(filename) && !FSCom.remove(filename)) + if (FSCom.exists(filename) && !FSCom.remove(filename)) { LOG_WARN("Can't remove old pref file\n"); - if (!renameFile(filenameTmp.c_str(), filename)) + } + if (!renameFile(filenameTmp.c_str(), filename)) { LOG_ERROR("Error: can't rename new pref file\n"); + } } else { LOG_ERROR("Can't write prefs\n"); #ifdef ARCH_NRF52 @@ -576,10 +572,10 @@ void NodeDB::saveToDisk(int saveWhat) } } -const meshtastic_NodeInfo *NodeDB::readNextInfo() +const meshtastic_NodeInfo *NodeDB::readNextInfo(uint32_t &readIndex) { - if (readPointer < *numNodes) - return &nodes[readPointer++]; + if (readIndex < *numNodes) + return &nodes[readIndex++]; else return NULL; } @@ -802,19 +798,19 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co // Print error to screen and serial port String lcd = String("Critical error ") + code + "!\n"; screen->print(lcd.c_str()); - if (filename) + if (filename) { LOG_ERROR("NOTE! Recording critical error %d at %s:%lu\n", code, filename, address); - else + } else { LOG_ERROR("NOTE! Recording critical error %d, address=0x%lx\n", code, address); + } // 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 541b51f83a..e0744865f6 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 @@ -46,8 +47,6 @@ class NodeDB meshtastic_NodeInfo *nodes; pb_size_t *numNodes; - uint32_t readPointer = 0; - 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 @@ -104,11 +103,8 @@ 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(); + const meshtastic_NodeInfo *readNextInfo(uint32_t &readIndex); /// pick a provisional nodenum we hope no one is using void pickNewNodeNum(); @@ -217,11 +213,25 @@ 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); +} + /** 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 + \ diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index cdda059137..5fc27a2b5a 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -40,9 +40,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 = NULL; // Don't keep returning old nodeinfos + resetReadIndex(); } void PhoneAPI::close() @@ -144,12 +143,11 @@ 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.refreshLocalNodeInfo(); // Update my NodeInfo because the client will be asking for it soon. break; case STATE_SEND_NODEINFO: { @@ -373,7 +371,7 @@ bool PhoneAPI::available() case STATE_SEND_NODEINFO: if (!nodeInfoForPhone) - nodeInfoForPhone = nodeDB.readNextInfo(); + nodeInfoForPhone = nodeDB.readNextInfo(readIndex); return true; // Always say we have something, because we might need to advance our state machine case STATE_SEND_PACKETS: { @@ -423,8 +421,9 @@ int PhoneAPI::onNotify(uint32_t newValue) if (state == STATE_SEND_PACKETS) { LOG_INFO("Telling client we have new packets %u\n", newValue); onNowHasData(newValue); - } else + } else { LOG_DEBUG("(Client not yet interested in packets)\n"); + } return 0; } diff --git a/src/mesh/PhoneAPI.h b/src/mesh/PhoneAPI.h index af8f1be269..2ea4d3a0cf 100644 --- a/src/mesh/PhoneAPI.h +++ b/src/mesh/PhoneAPI.h @@ -58,6 +58,9 @@ class PhoneAPI /// 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/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 0d53dc8878..00af93e153 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); } @@ -241,6 +242,7 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(float snr) void printPacket(const char *prefix, const meshtastic_MeshPacket *p) { +#ifdef DEBUG_PORT std::string out = DEBUG_PORT.mt_sprintf("%s (id=0x%08x fr=0x%02x to=0x%02x, WantAck=%d, HopLim=%d Ch=0x%x", prefix, p->id, p->from & 0xff, p->to & 0xff, p->want_ack, p->hop_limit, p->channel); if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) { @@ -283,6 +285,7 @@ void printPacket(const char *prefix, const meshtastic_MeshPacket *p) out += ")"; LOG_DEBUG("%s\n", out.c_str()); +#endif } RadioInterface::RadioInterface() diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index 8fd7157183..a74d410903 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -78,8 +78,9 @@ bool RadioLibInterface::canSendImmediately() bool busyRx = isReceiving && isActivelyReceiving(); if (busyTx || busyRx) { - if (busyTx) + if (busyTx) { LOG_WARN("Can not send yet, busyTx\n"); + } // If we've been trying to send the same packet more than one minute and we haven't gotten a // TX IRQ from the radio, the radio is probably broken. if (busyTx && (millis() - lastTxStart > 60000)) { @@ -88,8 +89,9 @@ bool RadioLibInterface::canSendImmediately() // reboot in 5 seconds when this condition occurs. rebootAtMsec = lastTxStart + 65000; } - if (busyRx) + if (busyRx) { LOG_WARN("Can not send yet, busyRx\n"); + } return false; } else return true; @@ -164,9 +166,9 @@ meshtastic_QueueStatus RadioLibInterface::getQueueStatus() bool RadioLibInterface::canSleep() { bool res = txQueue.empty(); - if (!res) // only print debug messages if we are vetoing sleep + if (!res) { // only print debug messages if we are vetoing sleep LOG_DEBUG("radio wait to sleep, txEmpty=%d\n", res); - + } return res; } @@ -404,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 6635089e5e..4634ca7eec 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/ReliableRouter.cpp b/src/mesh/ReliableRouter.cpp index 7f5c9b7fc4..946a669cc0 100644 --- a/src/mesh/ReliableRouter.cpp +++ b/src/mesh/ReliableRouter.cpp @@ -104,13 +104,14 @@ void ReliableRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas if (p->to == ourNode) { // ignore ack/nak/want_ack packets that are not address to us (we only handle 0 hop reliability) if (p->want_ack) { - if (MeshModule::currentReply) + if (MeshModule::currentReply) { LOG_DEBUG("Some other module has replied to this message, no need for a 2nd ack\n"); - else if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) + } else if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) { sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel); - else + } else { // Send a 'NO_CHANNEL' error on the primary channel if want_ack packet destined for us cannot be decoded sendAckNak(meshtastic_Routing_Error_NO_CHANNEL, getFrom(p), p->id, channels.getPrimaryIndex()); + } } // We consider an ack to be either a !routing packet with a request ID or a routing packet with !error diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index e85d85450c..156b482093 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -211,8 +211,10 @@ ErrorCode Router::send(meshtastic_MeshPacket *p) if (!config.lora.override_duty_cycle && myRegion->dutyCycle < 100) { float hourlyTxPercent = airTime->utilizationTXPercent(); if (hourlyTxPercent > myRegion->dutyCycle) { +#ifdef DEBUG_PORT uint8_t silentMinutes = airTime->getSilentMinutes(hourlyTxPercent, myRegion->dutyCycle); LOG_WARN("Duty cycle limit exceeded. Aborting send for now, you can send again in %d minutes.\n", silentMinutes); +#endif meshtastic_Routing_Error err = meshtastic_Routing_Error_DUTY_CYCLE_LIMIT; if (getFrom(p) == nodeDB.getNodeNum()) { // only send NAK to API, not to the mesh abortSendAndNak(err, p); @@ -479,9 +481,9 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p) // assert(radioConfig.has_preferences); bool ignore = is_in_repeated(config.lora.ignore_incoming, p->from); - if (ignore) + if (ignore) { LOG_DEBUG("Ignoring incoming message, 0x%x is in our ignore list\n", p->from); - else if (ignore |= shouldFilterReceived(p)) { + } else if (ignore |= shouldFilterReceived(p)) { LOG_DEBUG("Incoming message was filtered 0x%x\n", p->from); } diff --git a/src/mesh/STM32WLE5JCInterface.cpp b/src/mesh/STM32WLE5JCInterface.cpp new file mode 100644 index 0000000000..5b6fd08442 --- /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 0000000000..73d53d92f9 --- /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/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp index c26b773f71..495840d50a 100644 --- a/src/mesh/SX126xInterface.cpp +++ b/src/mesh/SX126xInterface.cpp @@ -60,16 +60,19 @@ template bool SX126xInterface::init() LOG_DEBUG("Current limit set to %f\n", currentLimit); LOG_DEBUG("Current limit set result %d\n", res); -#ifdef SX126X_E22 +#if defined(SX126X_E22) // E22 Emulation explicitly requires DIO2 as RF switch, so set it to TRUE again for good measure. In case somebody defines // SX126X_TX for an E22 Module - if (res == RADIOLIB_ERR_NONE) + if (res == RADIOLIB_ERR_NONE) { + LOG_DEBUG("SX126X_E22 mode enabled. Setting DIO2 as RF Switch\n"); res = lora.setDio2AsRfSwitch(true); + } #endif #if defined(SX126X_TXEN) && (SX126X_TXEN != RADIOLIB_NC) // lora.begin sets Dio2 as RF switch control, which is not true if we are manually controlling RX and TX if (res == RADIOLIB_ERR_NONE) { + LOG_DEBUG("SX126X_TX/RX EN pins defined. Setting RF Switch: RXEN=%i, TXEN=%i\n", SX126X_RXEN, SX126X_TXEN); res = lora.setDio2AsRfSwitch(false); lora.setRfSwitchPins(SX126X_RXEN, SX126X_TXEN); } @@ -176,8 +179,9 @@ template void SX126xInterface::setStandby() int err = lora.standby(); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { LOG_DEBUG("SX126x standby failed with error %d\n", err); + } assert(err == RADIOLIB_ERR_NONE); diff --git a/src/mesh/SX128xInterface.cpp b/src/mesh/SX128xInterface.cpp index 691d5dff03..9c3ec3e914 100644 --- a/src/mesh/SX128xInterface.cpp +++ b/src/mesh/SX128xInterface.cpp @@ -151,8 +151,9 @@ template void SX128xInterface::setStandby() int err = lora.standby(); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { LOG_ERROR("SX128x standby failed with error %d\n", err); + } assert(err == RADIOLIB_ERR_NONE); diff --git a/src/mesh/TypedQueue.h b/src/mesh/TypedQueue.h index 721eec2c01..c08f9183b2 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 659de05f85..c60e35394e 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/admin.pb.c b/src/mesh/generated/meshtastic/admin.pb.c index c897c17607..92835c89cc 100644 --- a/src/mesh/generated/meshtastic/admin.pb.c +++ b/src/mesh/generated/meshtastic/admin.pb.c @@ -12,6 +12,9 @@ PB_BIND(meshtastic_AdminMessage, meshtastic_AdminMessage, 2) PB_BIND(meshtastic_HamParameters, meshtastic_HamParameters, AUTO) +PB_BIND(meshtastic_NodeRemoteHardwarePinsResponse, meshtastic_NodeRemoteHardwarePinsResponse, 2) + + diff --git a/src/mesh/generated/meshtastic/admin.pb.h b/src/mesh/generated/meshtastic/admin.pb.h index 2518f199e6..b6162b8466 100644 --- a/src/mesh/generated/meshtastic/admin.pb.h +++ b/src/mesh/generated/meshtastic/admin.pb.h @@ -6,9 +6,10 @@ #include #include "meshtastic/channel.pb.h" #include "meshtastic/config.pb.h" +#include "meshtastic/connection_status.pb.h" +#include "meshtastic/deviceonly.pb.h" #include "meshtastic/mesh.pb.h" #include "meshtastic/module_config.pb.h" -#include "meshtastic/connection_status.pb.h" #if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. @@ -70,6 +71,13 @@ typedef struct _meshtastic_HamParameters { char short_name[6]; } meshtastic_HamParameters; +/* Response envelope for node_remote_hardware_pins */ +typedef struct _meshtastic_NodeRemoteHardwarePinsResponse { + /* Nodes and their respective remote hardware GPIO pins */ + pb_size_t node_remote_hardware_pins_count; + meshtastic_NodeRemoteHardwarePin node_remote_hardware_pins[16]; +} meshtastic_NodeRemoteHardwarePinsResponse; + /* This message is handled by the Admin module and is responsible for all settings/channel read/write operations. This message is used to do settings operations to both remote AND local nodes. (Prior to 1.2 these operations were done via special ToRadio operations) */ @@ -111,6 +119,10 @@ typedef struct _meshtastic_AdminMessage { meshtastic_DeviceConnectionStatus get_device_connection_status_response; /* Setup a node for licensed amateur (ham) radio operation */ meshtastic_HamParameters set_ham_mode; + /* Get the mesh's nodes with their available gpio pins for RemoteHardware module use */ + bool get_node_remote_hardware_pins_request; + /* Respond with the mesh's nodes with their available gpio pins for RemoteHardware module use */ + meshtastic_NodeRemoteHardwarePinsResponse get_node_remote_hardware_pins_response; /* Set the owner for this node */ meshtastic_User set_owner; /* Set channels (using the new API). @@ -168,17 +180,21 @@ extern "C" { + /* Initializer values for message structs */ #define meshtastic_AdminMessage_init_default {0, {0}} #define meshtastic_HamParameters_init_default {"", 0, 0, ""} +#define meshtastic_NodeRemoteHardwarePinsResponse_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, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}} #define meshtastic_AdminMessage_init_zero {0, {0}} #define meshtastic_HamParameters_init_zero {"", 0, 0, ""} +#define meshtastic_NodeRemoteHardwarePinsResponse_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, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}} /* Field tags (for use in manual encoding/decoding) */ #define meshtastic_HamParameters_call_sign_tag 1 #define meshtastic_HamParameters_tx_power_tag 2 #define meshtastic_HamParameters_frequency_tag 3 #define meshtastic_HamParameters_short_name_tag 4 +#define meshtastic_NodeRemoteHardwarePinsResponse_node_remote_hardware_pins_tag 1 #define meshtastic_AdminMessage_get_channel_request_tag 1 #define meshtastic_AdminMessage_get_channel_response_tag 2 #define meshtastic_AdminMessage_get_owner_request_tag 3 @@ -196,6 +212,8 @@ extern "C" { #define meshtastic_AdminMessage_get_device_connection_status_request_tag 16 #define meshtastic_AdminMessage_get_device_connection_status_response_tag 17 #define meshtastic_AdminMessage_set_ham_mode_tag 18 +#define meshtastic_AdminMessage_get_node_remote_hardware_pins_request_tag 19 +#define meshtastic_AdminMessage_get_node_remote_hardware_pins_response_tag 20 #define meshtastic_AdminMessage_set_owner_tag 32 #define meshtastic_AdminMessage_set_channel_tag 33 #define meshtastic_AdminMessage_set_config_tag 34 @@ -230,6 +248,8 @@ X(a, STATIC, ONEOF, STRING, (payload_variant,get_ringtone_response,get_ri X(a, STATIC, ONEOF, BOOL, (payload_variant,get_device_connection_status_request,get_device_connection_status_request), 16) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_device_connection_status_response,get_device_connection_status_response), 17) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_ham_mode,set_ham_mode), 18) \ +X(a, STATIC, ONEOF, BOOL, (payload_variant,get_node_remote_hardware_pins_request,get_node_remote_hardware_pins_request), 19) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_node_remote_hardware_pins_response,get_node_remote_hardware_pins_response), 20) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_owner,set_owner), 32) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_channel,set_channel), 33) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_config,set_config), 34) \ @@ -253,6 +273,7 @@ X(a, STATIC, ONEOF, INT32, (payload_variant,nodedb_reset,nodedb_reset), #define meshtastic_AdminMessage_payload_variant_get_device_metadata_response_MSGTYPE meshtastic_DeviceMetadata #define meshtastic_AdminMessage_payload_variant_get_device_connection_status_response_MSGTYPE meshtastic_DeviceConnectionStatus #define meshtastic_AdminMessage_payload_variant_set_ham_mode_MSGTYPE meshtastic_HamParameters +#define meshtastic_AdminMessage_payload_variant_get_node_remote_hardware_pins_response_MSGTYPE meshtastic_NodeRemoteHardwarePinsResponse #define meshtastic_AdminMessage_payload_variant_set_owner_MSGTYPE meshtastic_User #define meshtastic_AdminMessage_payload_variant_set_channel_MSGTYPE meshtastic_Channel #define meshtastic_AdminMessage_payload_variant_set_config_MSGTYPE meshtastic_Config @@ -266,16 +287,25 @@ X(a, STATIC, SINGULAR, STRING, short_name, 4) #define meshtastic_HamParameters_CALLBACK NULL #define meshtastic_HamParameters_DEFAULT NULL +#define meshtastic_NodeRemoteHardwarePinsResponse_FIELDLIST(X, a) \ +X(a, STATIC, REPEATED, MESSAGE, node_remote_hardware_pins, 1) +#define meshtastic_NodeRemoteHardwarePinsResponse_CALLBACK NULL +#define meshtastic_NodeRemoteHardwarePinsResponse_DEFAULT NULL +#define meshtastic_NodeRemoteHardwarePinsResponse_node_remote_hardware_pins_MSGTYPE meshtastic_NodeRemoteHardwarePin + extern const pb_msgdesc_t meshtastic_AdminMessage_msg; extern const pb_msgdesc_t meshtastic_HamParameters_msg; +extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePinsResponse_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define meshtastic_AdminMessage_fields &meshtastic_AdminMessage_msg #define meshtastic_HamParameters_fields &meshtastic_HamParameters_msg +#define meshtastic_NodeRemoteHardwarePinsResponse_fields &meshtastic_NodeRemoteHardwarePinsResponse_msg /* Maximum encoded size of messages (where known) */ -#define meshtastic_AdminMessage_size 234 +#define meshtastic_AdminMessage_size 500 #define meshtastic_HamParameters_size 32 +#define meshtastic_NodeRemoteHardwarePinsResponse_size 496 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index e3b6e242d8..99314aef5f 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -18,7 +18,7 @@ typedef enum _meshtastic_Config_DeviceConfig_Role { Same as a client except packets will not hop over this node, does not contribute to routing packets for mesh. */ meshtastic_Config_DeviceConfig_Role_CLIENT_MUTE = 1, /* Router device role. - Mesh packets will prefer to be routed over this node. This node will not be used by client apps. + Mesh packets will prefer to be routed over this node. This node will not be used by client apps. The wifi/ble radios and the oled screen will be put to sleep. This mode may still potentially have higher power usage due to it's preference in message rebroadcasting on the mesh. */ meshtastic_Config_DeviceConfig_Role_ROUTER = 2, @@ -233,6 +233,9 @@ typedef struct _meshtastic_Config_DeviceConfig { uint32_t node_info_broadcast_secs; /* Treat double tap interrupt on supported accelerometers as a button press if set to true */ bool double_tap_as_button_press; + /* If true, device is considered to be "managed" by a mesh administrator + Clients should then limit available configuration and administrative options inside the user interface */ + bool is_managed; } meshtastic_Config_DeviceConfig; /* Position Config */ @@ -290,7 +293,7 @@ typedef struct _meshtastic_Config_PowerConfig { 0 for default of 1 minute */ uint32_t wait_bluetooth_secs; /* Mesh Super Deep Sleep Timeout Seconds - While in Light Sleep if this value is exceeded we will lower into super deep sleep + While in Light Sleep if this value is exceeded we will lower into super deep sleep for sds_secs (default 1 year) or a button press 0 for default of two hours, MAXUINT for disabled */ uint32_t mesh_sds_timeout_secs; @@ -308,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 { @@ -353,7 +358,7 @@ typedef struct _meshtastic_Config_DisplayConfig { /* Automatically toggles to the next page on the screen like a carousel, based the specified interval in seconds. Potentially useful for devices without user buttons. */ uint32_t auto_screen_carousel_secs; - /* If this is set, the displayed compass will always point north. if unset, the old behaviour + /* If this is set, the displayed compass will always point north. if unset, the old behaviour (top of display is heading direction) is used. */ bool compass_north_top; /* Flip screen vertically, for cases that mount the screen upside down */ @@ -416,7 +421,7 @@ typedef struct _meshtastic_Config_LoRaConfig { If using the hash algorithm the channel number will be: hash(channel_name) % NUM_CHANNELS (Where num channels depends on the regulatory region). */ uint16_t channel_num; - /* If true, duty cycle limits will be exceeded and thus you're possibly not following + /* If true, duty cycle limits will be exceeded and thus you're possibly not following the local regulations if you're not a HAM. Has no effect if the duty cycle of the used region is 100%. */ bool override_duty_cycle; @@ -529,18 +534,18 @@ extern "C" { /* Initializer values for message structs */ #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} +#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} #define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}} #define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0} #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} +#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} @@ -556,6 +561,7 @@ extern "C" { #define meshtastic_Config_DeviceConfig_rebroadcast_mode_tag 6 #define meshtastic_Config_DeviceConfig_node_info_broadcast_secs_tag 7 #define meshtastic_Config_DeviceConfig_double_tap_as_button_press_tag 8 +#define meshtastic_Config_DeviceConfig_is_managed_tag 9 #define meshtastic_Config_PositionConfig_position_broadcast_secs_tag 1 #define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2 #define meshtastic_Config_PositionConfig_fixed_position_tag 3 @@ -575,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 @@ -650,7 +657,8 @@ X(a, STATIC, SINGULAR, UINT32, button_gpio, 4) \ X(a, STATIC, SINGULAR, UINT32, buzzer_gpio, 5) \ X(a, STATIC, SINGULAR, UENUM, rebroadcast_mode, 6) \ X(a, STATIC, SINGULAR, UINT32, node_info_broadcast_secs, 7) \ -X(a, STATIC, SINGULAR, BOOL, double_tap_as_button_press, 8) +X(a, STATIC, SINGULAR, BOOL, double_tap_as_button_press, 8) \ +X(a, STATIC, SINGULAR, BOOL, is_managed, 9) #define meshtastic_Config_DeviceConfig_CALLBACK NULL #define meshtastic_Config_DeviceConfig_DEFAULT NULL @@ -677,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 @@ -765,13 +774,13 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg; /* Maximum encoded size of messages (where known) */ #define meshtastic_Config_BluetoothConfig_size 10 -#define meshtastic_Config_DeviceConfig_size 28 +#define meshtastic_Config_DeviceConfig_size 30 #define meshtastic_Config_DisplayConfig_size 28 #define meshtastic_Config_LoRaConfig_size 77 #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 f3d27d086d..82c3fc44c5 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.c +++ b/src/mesh/generated/meshtastic/deviceonly.pb.c @@ -9,11 +9,20 @@ 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) PB_BIND(meshtastic_OEMStore, meshtastic_OEMStore, 2) +PB_BIND(meshtastic_NodeRemoteHardwarePin, meshtastic_NodeRemoteHardwarePin, AUTO) + + diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index d08c18ba9f..48f93da5e4 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -7,6 +7,8 @@ #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 #error Regenerate this file with the current version of nanopb generator. @@ -24,44 +26,46 @@ typedef enum _meshtastic_ScreenFonts { } meshtastic_ScreenFonts; /* Struct definitions */ -/* This message is never sent over the wire, but it is used for serializing DB - state to flash in the device code - FIXME, since we write this each time we enter deep sleep (and have infinite - flash) it would be better to use some sort of append only data structure for - the receive queue and use the preferences store for the other stuff */ -typedef struct _meshtastic_DeviceState { - /* Read only settings/info about this node */ - bool has_my_node; - meshtastic_MyNodeInfo my_node; - /* My owner info */ - bool has_owner; - meshtastic_User owner; +/* 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 */ - pb_size_t node_db_count; - meshtastic_NodeInfo node_db[80]; - /* Received packets saved for delivery to the phone */ - pb_size_t receive_queue_count; - meshtastic_MeshPacket receive_queue[1]; - /* We keep the last received text message (only) stored in the device flash, - so we can show it on the screen. - Might be null */ - bool has_rx_text_message; - meshtastic_MeshPacket rx_text_message; - /* A version integer used to invalidate old save files when we make - incompatible changes This integer is set at build time and is private to - NodeDB.cpp in the device code. */ - uint32_t version; - /* Used only during development. - Indicates developer is testing and changes should never be saved to flash. */ - bool no_save; - /* Some GPS receivers seem to have bogus settings from the factory, so we always do one factory reset. */ - bool did_gps_reset; - /* We keep the last received waypoint stored in the device flash, - so we can show it on the screen. - Might be null */ - bool has_rx_waypoint; - meshtastic_MeshPacket rx_waypoint; -} meshtastic_DeviceState; + 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 { @@ -99,6 +103,61 @@ typedef struct _meshtastic_OEMStore { meshtastic_LocalModuleConfig oem_local_module_config; } meshtastic_OEMStore; +/* RemoteHardwarePins associated with a node */ +typedef struct _meshtastic_NodeRemoteHardwarePin { + /* The node_num exposing the available gpio pin */ + uint32_t node_num; + /* The the available gpio pin for usage with RemoteHardware module */ + bool has_pin; + meshtastic_RemoteHardwarePin pin; +} meshtastic_NodeRemoteHardwarePin; + +/* This message is never sent over the wire, but it is used for serializing DB + state to flash in the device code + FIXME, since we write this each time we enter deep sleep (and have infinite + flash) it would be better to use some sort of append only data structure for + the receive queue and use the preferences store for the other stuff */ +typedef struct _meshtastic_DeviceState { + /* Read only settings/info about this node */ + bool has_my_node; + meshtastic_MyNodeInfo my_node; + /* My owner info */ + bool has_owner; + meshtastic_User owner; + /* 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 */ + pb_size_t receive_queue_count; + meshtastic_MeshPacket receive_queue[1]; + /* We keep the last received text message (only) stored in the device flash, + so we can show it on the screen. + Might be null */ + bool has_rx_text_message; + meshtastic_MeshPacket rx_text_message; + /* A version integer used to invalidate old save files when we make + incompatible changes This integer is set at build time and is private to + NodeDB.cpp in the device code. */ + uint32_t version; + /* Used only during development. + Indicates developer is testing and changes should never be saved to flash. */ + bool no_save; + /* Some GPS receivers seem to have bogus settings from the factory, so we always do one factory reset. */ + bool did_gps_reset; + /* We keep the last received waypoint stored in the device flash, + so we can show it on the screen. + Might be null */ + bool has_rx_waypoint; + meshtastic_MeshPacket rx_waypoint; + /* 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; + #ifdef __cplusplus extern "C" { @@ -111,27 +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} +#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_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} +#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}, 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_DeviceState_my_node_tag 2 -#define meshtastic_DeviceState_owner_tag 3 -#define meshtastic_DeviceState_node_db_tag 4 -#define meshtastic_DeviceState_receive_queue_tag 5 -#define meshtastic_DeviceState_rx_text_message_tag 7 -#define meshtastic_DeviceState_version_tag 8 -#define meshtastic_DeviceState_no_save_tag 9 -#define meshtastic_DeviceState_did_gps_reset_tag 11 -#define meshtastic_DeviceState_rx_waypoint_tag 12 +#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 @@ -142,6 +214,19 @@ extern "C" { #define meshtastic_OEMStore_oem_aes_key_tag 6 #define meshtastic_OEMStore_oem_local_config_tag 7 #define meshtastic_OEMStore_oem_local_module_config_tag 8 +#define meshtastic_NodeRemoteHardwarePin_node_num_tag 1 +#define meshtastic_NodeRemoteHardwarePin_pin_tag 2 +#define meshtastic_DeviceState_my_node_tag 2 +#define meshtastic_DeviceState_owner_tag 3 +#define meshtastic_DeviceState_node_db_tag 4 +#define meshtastic_DeviceState_receive_queue_tag 5 +#define meshtastic_DeviceState_rx_text_message_tag 7 +#define meshtastic_DeviceState_version_tag 8 +#define meshtastic_DeviceState_no_save_tag 9 +#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) \ @@ -153,7 +238,9 @@ X(a, STATIC, OPTIONAL, MESSAGE, rx_text_message, 7) \ 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, OPTIONAL, MESSAGE, rx_waypoint, 12) \ +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 @@ -162,6 +249,31 @@ X(a, STATIC, OPTIONAL, MESSAGE, rx_waypoint, 12) #define meshtastic_DeviceState_receive_queue_MSGTYPE meshtastic_MeshPacket #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) \ @@ -184,19 +296,35 @@ X(a, STATIC, OPTIONAL, MESSAGE, oem_local_module_config, 8) #define meshtastic_OEMStore_oem_local_config_MSGTYPE meshtastic_LocalConfig #define meshtastic_OEMStore_oem_local_module_config_MSGTYPE meshtastic_LocalModuleConfig +#define meshtastic_NodeRemoteHardwarePin_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, node_num, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, pin, 2) +#define meshtastic_NodeRemoteHardwarePin_CALLBACK NULL +#define meshtastic_NodeRemoteHardwarePin_DEFAULT NULL +#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 22364 -#define meshtastic_OEMStore_size 3041 +#define meshtastic_DeviceState_size 35056 +#define meshtastic_NodeInfoLite_size 151 +#define meshtastic_NodeRemoteHardwarePin_size 29 +#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 0cfcb24911..d70acc7fc7 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 456 -#define meshtastic_LocalModuleConfig_size 439 +#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 984939702f..0ed2f8e68d 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; @@ -719,6 +734,8 @@ typedef struct _meshtastic_DeviceMetadata { uint32_t position_flags; /* Device hardware model */ meshtastic_HardwareModel hw_model; + /* Has Remote Hardware enabled */ + bool hasRemoteHardware; } meshtastic_DeviceMetadata; /* Packets from the radio to the phone will appear on the fromRadio characteristic. @@ -855,7 +872,7 @@ extern "C" { #define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}} #define meshtastic_NeighborInfo_init_default {0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}} #define meshtastic_Neighbor_init_default {0, 0} -#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN} +#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0} #define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0} #define meshtastic_RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}} @@ -872,7 +889,7 @@ extern "C" { #define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}} #define meshtastic_NeighborInfo_init_zero {0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}} #define meshtastic_Neighbor_init_zero {0, 0} -#define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN} +#define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0} /* Field tags (for use in manual encoding/decoding) */ #define meshtastic_Position_latitude_i_tag 1 @@ -987,6 +1004,7 @@ extern "C" { #define meshtastic_DeviceMetadata_role_tag 7 #define meshtastic_DeviceMetadata_position_flags_tag 8 #define meshtastic_DeviceMetadata_hw_model_tag 9 +#define meshtastic_DeviceMetadata_hasRemoteHardware_tag 10 #define meshtastic_FromRadio_id_tag 1 #define meshtastic_FromRadio_packet_tag 2 #define meshtastic_FromRadio_my_info_tag 3 @@ -1210,7 +1228,8 @@ X(a, STATIC, SINGULAR, BOOL, hasBluetooth, 5) \ X(a, STATIC, SINGULAR, BOOL, hasEthernet, 6) \ X(a, STATIC, SINGULAR, UENUM, role, 7) \ X(a, STATIC, SINGULAR, UINT32, position_flags, 8) \ -X(a, STATIC, SINGULAR, UENUM, hw_model, 9) +X(a, STATIC, SINGULAR, UENUM, hw_model, 9) \ +X(a, STATIC, SINGULAR, BOOL, hasRemoteHardware, 10) #define meshtastic_DeviceMetadata_CALLBACK NULL #define meshtastic_DeviceMetadata_DEFAULT NULL @@ -1254,7 +1273,7 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg; /* Maximum encoded size of messages (where known) */ #define meshtastic_Compressed_size 243 #define meshtastic_Data_size 270 -#define meshtastic_DeviceMetadata_size 44 +#define meshtastic_DeviceMetadata_size 46 #define meshtastic_FromRadio_size 330 #define meshtastic_LogRecord_size 81 #define meshtastic_MeshPacket_size 321 diff --git a/src/mesh/generated/meshtastic/module_config.pb.c b/src/mesh/generated/meshtastic/module_config.pb.c index 0878be909d..9352feb177 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) @@ -36,6 +39,10 @@ PB_BIND(meshtastic_ModuleConfig_TelemetryConfig, meshtastic_ModuleConfig_Telemet PB_BIND(meshtastic_ModuleConfig_CannedMessageConfig, meshtastic_ModuleConfig_CannedMessageConfig, AUTO) +PB_BIND(meshtastic_RemoteHardwarePin, meshtastic_RemoteHardwarePin, AUTO) + + + diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h index e59d33dd0d..6273a89aed 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -10,6 +10,15 @@ #endif /* Enum definitions */ +typedef enum _meshtastic_RemoteHardwarePinType { + /* Unset/unused */ + meshtastic_RemoteHardwarePinType_UNKNOWN = 0, + /* GPIO pin can be read (if it is high / low) */ + meshtastic_RemoteHardwarePinType_DIGITAL_READ = 1, + /* GPIO pin can be written to (high / low) */ + meshtastic_RemoteHardwarePinType_DIGITAL_WRITE = 2 +} meshtastic_RemoteHardwarePinType; + /* Baudrate for codec2 voice */ typedef enum _meshtastic_ModuleConfig_AudioConfig_Audio_Baud { meshtastic_ModuleConfig_AudioConfig_Audio_Baud_CODEC2_DEFAULT = 0, @@ -49,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 */ @@ -103,11 +114,14 @@ typedef struct _meshtastic_ModuleConfig_MQTTConfig { char root[16]; } meshtastic_ModuleConfig_MQTTConfig; -/* RemoteHardwareModule Config */ -typedef struct _meshtastic_ModuleConfig_RemoteHardwareConfig { +/* NeighborInfoModule Config */ +typedef struct _meshtastic_ModuleConfig_NeighborInfoConfig { /* Whether the Module is enabled */ bool enabled; -} meshtastic_ModuleConfig_RemoteHardwareConfig; + /* 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 { @@ -129,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 */ @@ -208,7 +225,7 @@ typedef struct _meshtastic_ModuleConfig_RangeTestConfig { bool enabled; /* Send out range test messages from this node */ uint32_t sender; - /* Bool value indicating that this node should save a RangeTest.csv file. + /* Bool value indicating that this node should save a RangeTest.csv file. ESP32 Only */ bool save; } meshtastic_ModuleConfig_RangeTestConfig; @@ -262,6 +279,27 @@ typedef struct _meshtastic_ModuleConfig_CannedMessageConfig { bool send_bell; } meshtastic_ModuleConfig_CannedMessageConfig; +/* A GPIO pin definition for remote hardware module */ +typedef struct _meshtastic_RemoteHardwarePin { + /* GPIO Pin number (must match Arduino) */ + uint8_t gpio_pin; + /* Name for the GPIO pin (i.e. Front gate, mailbox, etc) */ + char name[15]; + /* Type of GPIO access available to consumers on the mesh */ + meshtastic_RemoteHardwarePinType type; +} meshtastic_RemoteHardwarePin; + +/* RemoteHardwareModule Config */ +typedef struct _meshtastic_ModuleConfig_RemoteHardwareConfig { + /* Whether the Module is enabled */ + bool enabled; + /* Whether the Module allows consumers to read / write to pins not defined in available_pins */ + bool allow_undefined_pin_access; + /* Exposes the available pins to the mesh for reading and writing */ + pb_size_t available_pins_count; + meshtastic_RemoteHardwarePin available_pins[4]; +} meshtastic_ModuleConfig_RemoteHardwareConfig; + /* Module Config */ typedef struct _meshtastic_ModuleConfig { pb_size_t which_payload_variant; @@ -284,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; @@ -293,6 +333,10 @@ extern "C" { #endif /* Helper constants for enums */ +#define _meshtastic_RemoteHardwarePinType_MIN meshtastic_RemoteHardwarePinType_UNKNOWN +#define _meshtastic_RemoteHardwarePinType_MAX meshtastic_RemoteHardwarePinType_DIGITAL_WRITE +#define _meshtastic_RemoteHardwarePinType_ARRAYSIZE ((meshtastic_RemoteHardwarePinType)(meshtastic_RemoteHardwarePinType_DIGITAL_WRITE+1)) + #define _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN meshtastic_ModuleConfig_AudioConfig_Audio_Baud_CODEC2_DEFAULT #define _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MAX meshtastic_ModuleConfig_AudioConfig_Audio_Baud_CODEC2_700B #define _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_ARRAYSIZE ((meshtastic_ModuleConfig_AudioConfig_Audio_Baud)(meshtastic_ModuleConfig_AudioConfig_Audio_Baud_CODEC2_700B+1)) @@ -302,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 @@ -312,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 @@ -325,28 +370,34 @@ extern "C" { #define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_event_ccw_ENUMTYPE meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar #define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_event_press_ENUMTYPE meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar +#define meshtastic_RemoteHardwarePin_type_ENUMTYPE meshtastic_RemoteHardwarePinType + /* Initializer values for message structs */ #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} +#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} #define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} +#define meshtastic_RemoteHardwarePin_init_default {0, "", _meshtastic_RemoteHardwarePinType_MIN} #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} +#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} #define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} +#define meshtastic_RemoteHardwarePin_init_zero {0, "", _meshtastic_RemoteHardwarePinType_MIN} /* Field tags (for use in manual encoding/decoding) */ #define meshtastic_ModuleConfig_MQTTConfig_enabled_tag 1 @@ -357,7 +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_RemoteHardwareConfig_enabled_tag 1 +#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 @@ -372,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 @@ -412,6 +465,12 @@ extern "C" { #define meshtastic_ModuleConfig_CannedMessageConfig_enabled_tag 9 #define meshtastic_ModuleConfig_CannedMessageConfig_allow_input_source_tag 10 #define meshtastic_ModuleConfig_CannedMessageConfig_send_bell_tag 11 +#define meshtastic_RemoteHardwarePin_gpio_pin_tag 1 +#define meshtastic_RemoteHardwarePin_name_tag 2 +#define meshtastic_RemoteHardwarePin_type_tag 3 +#define meshtastic_ModuleConfig_RemoteHardwareConfig_enabled_tag 1 +#define meshtastic_ModuleConfig_RemoteHardwareConfig_allow_undefined_pin_access_tag 2 +#define meshtastic_ModuleConfig_RemoteHardwareConfig_available_pins_tag 3 #define meshtastic_ModuleConfig_mqtt_tag 1 #define meshtastic_ModuleConfig_serial_tag 2 #define meshtastic_ModuleConfig_external_notification_tag 3 @@ -421,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) \ @@ -432,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 @@ -444,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) \ @@ -458,9 +520,18 @@ X(a, STATIC, SINGULAR, STRING, root, 8) #define meshtastic_ModuleConfig_MQTTConfig_DEFAULT NULL #define meshtastic_ModuleConfig_RemoteHardwareConfig_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, enabled, 1) +X(a, STATIC, SINGULAR, BOOL, enabled, 1) \ +X(a, STATIC, SINGULAR, BOOL, allow_undefined_pin_access, 2) \ +X(a, STATIC, REPEATED, MESSAGE, available_pins, 3) #define meshtastic_ModuleConfig_RemoteHardwareConfig_CALLBACK NULL #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) \ @@ -480,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 @@ -544,9 +616,17 @@ X(a, STATIC, SINGULAR, BOOL, send_bell, 11) #define meshtastic_ModuleConfig_CannedMessageConfig_CALLBACK NULL #define meshtastic_ModuleConfig_CannedMessageConfig_DEFAULT NULL +#define meshtastic_RemoteHardwarePin_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, gpio_pin, 1) \ +X(a, STATIC, SINGULAR, STRING, name, 2) \ +X(a, STATIC, SINGULAR, UENUM, type, 3) +#define meshtastic_RemoteHardwarePin_CALLBACK NULL +#define meshtastic_RemoteHardwarePin_DEFAULT NULL + 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; @@ -554,11 +634,13 @@ extern const pb_msgdesc_t meshtastic_ModuleConfig_StoreForwardConfig_msg; extern const pb_msgdesc_t meshtastic_ModuleConfig_RangeTestConfig_msg; extern const pb_msgdesc_t meshtastic_ModuleConfig_TelemetryConfig_msg; extern const pb_msgdesc_t meshtastic_ModuleConfig_CannedMessageConfig_msg; +extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #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 @@ -566,18 +648,21 @@ extern const pb_msgdesc_t meshtastic_ModuleConfig_CannedMessageConfig_msg; #define meshtastic_ModuleConfig_RangeTestConfig_fields &meshtastic_ModuleConfig_RangeTestConfig_msg #define meshtastic_ModuleConfig_TelemetryConfig_fields &meshtastic_ModuleConfig_TelemetryConfig_msg #define meshtastic_ModuleConfig_CannedMessageConfig_fields &meshtastic_ModuleConfig_CannedMessageConfig_msg +#define meshtastic_RemoteHardwarePin_fields &meshtastic_RemoteHardwarePin_msg /* Maximum encoded size of messages (where known) */ #define meshtastic_ModuleConfig_AudioConfig_size 19 #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 2 -#define meshtastic_ModuleConfig_SerialConfig_size 26 +#define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96 +#define meshtastic_ModuleConfig_SerialConfig_size 28 #define meshtastic_ModuleConfig_StoreForwardConfig_size 22 #define meshtastic_ModuleConfig_TelemetryConfig_size 26 #define meshtastic_ModuleConfig_size 223 +#define meshtastic_RemoteHardwarePin_size 21 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/portnums.pb.h b/src/mesh/generated/meshtastic/portnums.pb.h index ccf94372ed..089d7b59f0 100644 --- a/src/mesh/generated/meshtastic/portnums.pb.h +++ b/src/mesh/generated/meshtastic/portnums.pb.h @@ -77,9 +77,9 @@ typedef enum _meshtastic_PortNum { Maintained by Github user a-f-G-U-C (a Meshtastic contributor) Project files at https://github.com/a-f-G-U-C/Meshtastic-ZPS */ meshtastic_PortNum_ZPS_APP = 68, - /* Used to let multiple instances of Linux native applications communicate + /* Used to let multiple instances of Linux native applications communicate as if they did using their LoRa chip. - Maintained by GitHub user GUVWAF. + Maintained by GitHub user GUVWAF. Project files at https://github.com/GUVWAF/Meshtasticator */ meshtastic_PortNum_SIMULATOR_APP = 69, /* Provides a traceroute functionality to show the route a packet towards diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index d5f8877348..ae254e7f7b 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -50,6 +50,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta // if handled == false, then let others look at this message also if they want bool handled = false; assert(r); + bool fromOthers = mp.from != 0 && mp.from != nodeDB.getNodeNum(); switch (r->which_payload_variant) { @@ -175,6 +176,14 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta handleGetDeviceConnectionStatus(mp); break; } + case meshtastic_AdminMessage_get_module_config_response_tag: { + LOG_INFO("Client is receiving a get_module_config response.\n"); + if (fromOthers && r->get_module_config_response.which_payload_variant == + meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG) { + handleGetModuleConfigResponse(mp, r); + } + break; + } #ifdef ARCH_PORTDUINO case meshtastic_AdminMessage_exit_simulator_tag: LOG_INFO("Exiting simulator\n"); @@ -205,6 +214,29 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta return handled; } +void AdminModule::handleGetModuleConfigResponse(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *r) +{ + // Skip if it's disabled or no pins are exposed + if (!r->get_module_config_response.payload_variant.remote_hardware.enabled || + !r->get_module_config_response.payload_variant.remote_hardware.available_pins) { + LOG_DEBUG("Remote hardware module disabled or no vailable_pins. Skipping...\n"); + return; + } + 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; + } + for (uint8_t j = 0; j < sizeof(r->get_module_config_response.payload_variant.remote_hardware.available_pins); j++) { + auto availablePin = r->get_module_config_response.payload_variant.remote_hardware.available_pins[j]; + if (i < devicestate.node_remote_hardware_pins_count) { + devicestate.node_remote_hardware_pins[i].node_num = mp.from; + devicestate.node_remote_hardware_pins[i].pin = availablePin; + } + i++; + } + } +} + /** * Setter methods */ @@ -487,6 +519,28 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const } } +void AdminModule::handleGetNodeRemoteHardwarePins(const meshtastic_MeshPacket &req) +{ + meshtastic_AdminMessage r = meshtastic_AdminMessage_init_default; + 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); +} + void AdminModule::handleGetDeviceMetadata(const meshtastic_MeshPacket &req) { meshtastic_AdminMessage r = meshtastic_AdminMessage_init_default; @@ -499,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; @@ -517,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; @@ -533,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/AdminModule.h b/src/modules/AdminModule.h index 7170e61d62..eb06e7b83d 100644 --- a/src/modules/AdminModule.h +++ b/src/modules/AdminModule.h @@ -26,15 +26,18 @@ class AdminModule : public ProtobufModule bool hasOpenEditTransaction = false; void saveChanges(int saveWhat, bool shouldReboot = true); + /** * Getters */ + void handleGetModuleConfigResponse(const meshtastic_MeshPacket &req, meshtastic_AdminMessage *p); void handleGetOwner(const meshtastic_MeshPacket &req); void handleGetConfig(const meshtastic_MeshPacket &req, uint32_t configType); void handleGetModuleConfig(const meshtastic_MeshPacket &req, uint32_t configType); void handleGetChannel(const meshtastic_MeshPacket &req, uint32_t channelIndex); void handleGetDeviceMetadata(const meshtastic_MeshPacket &req); void handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &req); + void handleGetNodeRemoteHardwarePins(const meshtastic_MeshPacket &req); /** * Setters */ diff --git a/src/modules/ExternalNotificationModule.h b/src/modules/ExternalNotificationModule.h index 7d4f54c2fe..f8ec053dd2 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 5d49a213ef..61de2c265c 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 ade96fb8a4..42066ad5b9 100644 --- a/src/modules/PositionModule.cpp +++ b/src/modules/PositionModule.cpp @@ -56,7 +56,7 @@ 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_NodeInfo *node = service.refreshLocalNodeInfo(); // should guarantee there is now a position assert(node->has_position); node->position.seq_number++; @@ -112,8 +112,9 @@ meshtastic_MeshPacket *PositionModule::allocReply() if (getRTCQuality() < RTCQualityDevice) { LOG_INFO("Stripping time %u from position send\n", p.time); p.time = 0; - } else + } else { LOG_INFO("Providing time to mesh %u\n", p.time); + } LOG_INFO("Position reply: time=%i, latI=%i, lonI=-%i\n", p.time, p.latitude_i, p.longitude_i); @@ -153,7 +154,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; @@ -170,9 +171,9 @@ int32_t PositionModule::runOnce() } 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_NodeInfo *node2 = service.refreshLocalNodeInfo(); // 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; diff --git a/src/modules/esp32/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp similarity index 94% rename from src/modules/esp32/RangeTestModule.cpp rename to src/modules/RangeTestModule.cpp index e8821f9a09..c1b1e48001 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 @@ -53,13 +53,13 @@ int32_t RangeTestModule::runOnce() if (moduleConfig.range_test.sender) { LOG_INFO("Initializing Range Test Module -- Sender\n"); - return (5000); // Sending first message 5 seconds after initilization. + started = millis(); // make a note of when we started + return (5000); // Sending first message 5 seconds after initilization. } else { LOG_INFO("Initializing Range Test Module -- Receiver\n"); return disable(); // This thread does not need to run as a receiver } - } else { if (moduleConfig.range_test.sender) { @@ -77,7 +77,13 @@ int32_t RangeTestModule::runOnce() rangeTestModuleRadio->sendPayload(); } - return (senderHeartbeat); + // If we have been running for more than 8 hours, turn module back off + if (millis() - started > 28800000) { + LOG_INFO("Range Test Module - Disabling after 8 hours\n"); + return disable(); + } else { + return (senderHeartbeat); + } } else { return disable(); // This thread does not need to run as a receiver @@ -115,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) { @@ -146,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); @@ -158,7 +163,6 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket LOG_DEBUG("-----------------------------------------\n"); */ } - } else { LOG_INFO("Range Test Module Disabled\n"); } @@ -170,6 +174,7 @@ 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)); @@ -186,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); @@ -277,6 +281,7 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp) fileToAppend.printf("\"%s\"\n", p.payload.bytes); fileToAppend.flush(); fileToAppend.close(); +#endif return 1; } diff --git a/src/modules/esp32/RangeTestModule.h b/src/modules/RangeTestModule.h similarity index 97% rename from src/modules/esp32/RangeTestModule.h rename to src/modules/RangeTestModule.h index 533621d47e..ae2a8f1829 100644 --- a/src/modules/esp32/RangeTestModule.h +++ b/src/modules/RangeTestModule.h @@ -9,6 +9,7 @@ class RangeTestModule : private concurrency::OSThread { bool firstTime = 1; + unsigned long started = 0; public: RangeTestModule(); diff --git a/src/modules/RemoteHardwareModule.cpp b/src/modules/RemoteHardwareModule.cpp index c3232d2660..3d4d735b43 100644 --- a/src/modules/RemoteHardwareModule.cpp +++ b/src/modules/RemoteHardwareModule.cpp @@ -53,7 +53,7 @@ bool RemoteHardwareModule::handleReceivedProtobuf(const meshtastic_MeshPacket &r { if (moduleConfig.remote_hardware.enabled) { auto p = *pptr; - LOG_INFO("Received RemoteHardware typ=%d\n", p.type); + LOG_INFO("Received RemoteHardware type=%d\n", p.type); switch (p.type) { case meshtastic_HardwareMessage_Type_WRITE_GPIOS: diff --git a/src/modules/ReplyModule.cpp b/src/modules/ReplyModule.cpp index 3bfad28ad6..439f6b7f7f 100644 --- a/src/modules/ReplyModule.cpp +++ b/src/modules/ReplyModule.cpp @@ -8,10 +8,12 @@ meshtastic_MeshPacket *ReplyModule::allocReply() { assert(currentRequest); // should always be !NULL +#ifdef DEBUG_PORT auto req = *currentRequest; auto &p = req.decoded; // The incoming message is in p.payload LOG_INFO("Received message from=0x%0x, id=%d, msg=%.*s\n", req.from, req.id, p.payload.size, p.payload.bytes); +#endif screen->print("Sending reply\n"); diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp index 35b83e6c69..b76f9de486 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; - - 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; + uint32_t baud = getBaudRate(); - } 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); } -#else - if (moduleConfig.serial.rxd && moduleConfig.serial.txd) +#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); - -#endif - if (moduleConfig.serial.timeout) { - Serial2.setTimeout(moduleConfig.serial.timeout); // Number of MS to wait to set the timeout for the string. + Serial2.begin(baud, SERIAL_8N1); + Serial2.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT); } else { - Serial2.setTimeout(TIMEOUT); // Number of MS to wait to set the timeout for the string. + Serial.begin(baud, SERIAL_8N1); + Serial.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); +#endif serialModuleRadio = new SerialModuleRadio(); firstTime = 0; @@ -186,9 +154,7 @@ 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) { @@ -196,16 +162,29 @@ int32_t SerialModule::runOnce() if (millis() - lastNmeaTime > 2000) { lastNmeaTime = millis(); printGGA(outbuf, sizeof(outbuf), nodeDB.getNode(myNodeInfo.my_node_num)->position); - Serial2.printf("%s", outbuf); + 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_NodeInfo *tempNodeInfo = nodeDB.readNextInfo(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.readNextInfo(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)); 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.getNode(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 } + +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 diff --git a/src/modules/SerialModule.h b/src/modules/SerialModule.h index cc696316d4..562ccd42b8 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/AirQualityTelemetry.cpp b/src/modules/Telemetry/AirQualityTelemetry.cpp index de74c0bf94..f87ea504bc 100644 --- a/src/modules/Telemetry/AirQualityTelemetry.cpp +++ b/src/modules/Telemetry/AirQualityTelemetry.cpp @@ -59,6 +59,7 @@ int32_t AirQualityTelemetryModule::runOnce() bool AirQualityTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t) { if (t->which_variant == meshtastic_Telemetry_air_quality_metrics_tag) { +#ifdef DEBUG_PORT const char *sender = getSenderShortName(mp); LOG_INFO("(Received from %s): pm10_standard=%i, pm25_standard=%i, pm100_standard=%i\n", sender, @@ -68,7 +69,7 @@ bool AirQualityTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPack LOG_INFO(" | PM1.0(Environmental)=%i, PM2.5(Environmental)=%i, PM10.0(Environmental)=%i\n", t->variant.air_quality_metrics.pm10_environmental, t->variant.air_quality_metrics.pm25_environmental, t->variant.air_quality_metrics.pm100_environmental); - +#endif // release previous packet before occupying a new spot if (lastMeasurementPacket != nullptr) packetPool.release(lastMeasurementPacket); diff --git a/src/modules/Telemetry/DeviceTelemetry.cpp b/src/modules/Telemetry/DeviceTelemetry.cpp index 199a90209e..4ef5a9a138 100644 --- a/src/modules/Telemetry/DeviceTelemetry.cpp +++ b/src/modules/Telemetry/DeviceTelemetry.cpp @@ -31,12 +31,13 @@ int32_t DeviceTelemetryModule::runOnce() bool DeviceTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t) { if (t->which_variant == meshtastic_Telemetry_device_metrics_tag) { +#ifdef DEBUG_PORT const char *sender = getSenderShortName(mp); LOG_INFO("(Received from %s): air_util_tx=%f, channel_utilization=%f, battery_level=%i, voltage=%f\n", sender, t->variant.device_metrics.air_util_tx, t->variant.device_metrics.channel_utilization, t->variant.device_metrics.battery_level, t->variant.device_metrics.voltage); - +#endif nodeDB.updateTelemetry(getFrom(&mp), *t, RX_SRC_RADIO); } return false; // Let others look at this message also if they want @@ -49,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", @@ -77,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 3b8a7dda1b..5cdc4bf4dc 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() @@ -183,6 +181,7 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t) { if (t->which_variant == meshtastic_Telemetry_environment_metrics_tag) { +#ifdef DEBUG_PORT const char *sender = getSenderShortName(mp); LOG_INFO("(Received from %s): barometric_pressure=%f, current=%f, gas_resistance=%f, relative_humidity=%f, " @@ -190,7 +189,7 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPac sender, t->variant.environment_metrics.barometric_pressure, t->variant.environment_metrics.current, t->variant.environment_metrics.gas_resistance, t->variant.environment_metrics.relative_humidity, t->variant.environment_metrics.temperature, t->variant.environment_metrics.voltage); - +#endif // release previous packet before occupying a new spot if (lastMeasurementPacket != nullptr) packetPool.release(lastMeasurementPacket); @@ -204,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; @@ -215,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); - - 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; - - 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); + valid = ina260Sensor.getMetrics(&m); + + 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; + + 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); + } } - 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 3340f87513..d6cd2137fa 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 43e4c03863..5b32645e67 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; @@ -92,10 +112,12 @@ void BME680Sensor::updateState() file.flush(); file.close(); // brief window of risk here ;-) - if (FSCom.exists(bsecConfigFileName) && !FSCom.remove(bsecConfigFileName)) + if (FSCom.exists(bsecConfigFileName) && !FSCom.remove(bsecConfigFileName)) { LOG_WARN("Can't remove old state file\n"); - if (!renameFile(filenameTmp.c_str(), bsecConfigFileName)) + } + if (!renameFile(filenameTmp.c_str(), bsecConfigFileName)) { LOG_ERROR("Error: can't rename new state file\n"); + } } else { LOG_INFO("Can't write %s state (File: %s).\n", sensorName, bsecConfigFileName); @@ -104,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 6b45a76f43..06e24b1a9d 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 bffa1e3677..1dd7f7f2c8 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 dc6c0a5afd..f11a571ccc 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 ee0256e621..034fecca0b 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 1dcb596e62..8ea5326973 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 7a579ef5c4..dec81e0614 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 0000000000..f2f28fb062 --- /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 0000000000..1f27e6c69c --- /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 0000000000..cdd209ae5d --- /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/TextMessageModule.cpp b/src/modules/TextMessageModule.cpp index 0fa175a144..8ff034fa93 100644 --- a/src/modules/TextMessageModule.cpp +++ b/src/modules/TextMessageModule.cpp @@ -7,8 +7,10 @@ TextMessageModule *textMessageModule; ProcessMessage TextMessageModule::handleReceived(const meshtastic_MeshPacket &mp) { +#ifdef DEBUG_PORT auto &p = mp.decoded; LOG_INFO("Received text msg from=0x%0x, id=0x%x, msg=%.*s\n", mp.from, mp.id, p.payload.size, p.payload.bytes); +#endif // We only store/display messages destined for us. // Keep a copy of the most recent text message. diff --git a/src/modules/TraceRouteModule.cpp b/src/modules/TraceRouteModule.cpp index 14396266dd..f26c40d2f0 100644 --- a/src/modules/TraceRouteModule.cpp +++ b/src/modules/TraceRouteModule.cpp @@ -47,6 +47,7 @@ void TraceRouteModule::appendMyID(meshtastic_RouteDiscovery *updated) void TraceRouteModule::printRoute(meshtastic_RouteDiscovery *r, uint32_t origin, uint32_t dest) { +#ifdef DEBUG_PORT LOG_INFO("Route traced:\n"); LOG_INFO("0x%x --> ", origin); for (uint8_t i = 0; i < r->route_count; i++) { @@ -56,6 +57,7 @@ void TraceRouteModule::printRoute(meshtastic_RouteDiscovery *r, uint32_t origin, LOG_INFO("0x%x\n", dest); else LOG_INFO("...\n"); +#endif } meshtastic_MeshPacket *TraceRouteModule::allocReply() diff --git a/src/modules/WaypointModule.cpp b/src/modules/WaypointModule.cpp index f95bdec34f..83485c8eee 100644 --- a/src/modules/WaypointModule.cpp +++ b/src/modules/WaypointModule.cpp @@ -7,8 +7,10 @@ WaypointModule *waypointModule; ProcessMessage WaypointModule::handleReceived(const meshtastic_MeshPacket &mp) { +#ifdef DEBUG_PORT auto &p = mp.decoded; LOG_INFO("Received waypoint msg from=0x%0x, id=0x%x, msg=%.*s\n", mp.from, mp.id, p.payload.size, p.payload.bytes); +#endif // We only store/display messages destined for us. // Keep a copy of the most recent text message. diff --git a/src/modules/esp32/AudioModule.cpp b/src/modules/esp32/AudioModule.cpp index e6a975119f..4a154878d4 100644 --- a/src/modules/esp32/AudioModule.cpp +++ b/src/modules/esp32/AudioModule.cpp @@ -195,8 +195,9 @@ int32_t AudioModule::runOnce() .tx_desc_auto_clear = true, .fixed_mclk = 0}; res = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL); - if (res != ESP_OK) + if (res != ESP_OK) { LOG_ERROR("Failed to install I2S driver: %d\n", res); + } const i2s_pin_config_t pin_config = { .bck_io_num = moduleConfig.audio.i2s_sck, @@ -204,12 +205,14 @@ int32_t AudioModule::runOnce() .data_out_num = moduleConfig.audio.i2s_din ? moduleConfig.audio.i2s_din : I2S_PIN_NO_CHANGE, .data_in_num = moduleConfig.audio.i2s_sd ? moduleConfig.audio.i2s_sd : I2S_PIN_NO_CHANGE}; res = i2s_set_pin(I2S_PORT, &pin_config); - if (res != ESP_OK) + if (res != ESP_OK) { LOG_ERROR("Failed to set I2S pin config: %d\n", res); + } res = i2s_start(I2S_PORT); - if (res != ESP_OK) + if (res != ESP_OK) { LOG_ERROR("Failed to start I2S: %d\n", res); + } radio_state = RadioState::rx; diff --git a/src/modules/esp32/StoreForwardModule.cpp b/src/modules/esp32/StoreForwardModule.cpp index 38e9836694..767e1fb2bb 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/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index bd1a856418..532a2d1258 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -461,8 +461,9 @@ std::string MQTT::downstreamPacketToJson(meshtastic_MeshPacket *mp) msgPayload["current"] = new JSONValue(decoded->variant.environment_metrics.current); } jsonObj["payload"] = new JSONValue(msgPayload); - } else + } else { LOG_ERROR("Error decoding protobuf for telemetry message!\n"); + } }; break; } @@ -479,8 +480,9 @@ std::string MQTT::downstreamPacketToJson(meshtastic_MeshPacket *mp) msgPayload["shortname"] = new JSONValue(decoded->short_name); msgPayload["hardware"] = new JSONValue(decoded->hw_model); jsonObj["payload"] = new JSONValue(msgPayload); - } else + } else { LOG_ERROR("Error decoding protobuf for nodeinfo message!\n"); + } }; break; } @@ -503,6 +505,15 @@ std::string MQTT::downstreamPacketToJson(meshtastic_MeshPacket *mp) if ((int)decoded->altitude) { msgPayload["altitude"] = new JSONValue((int)decoded->altitude); } + if ((int)decoded->ground_speed) { + msgPayload["ground_speed"] = new JSONValue((int)decoded->ground_speed); + } + if (int(decoded->ground_track)) { + msgPayload["ground_track"] = new JSONValue((int)decoded->ground_track); + } + if (int(decoded->sats_in_view)) { + msgPayload["sats_in_view"] = new JSONValue((int)decoded->sats_in_view); + } jsonObj["payload"] = new JSONValue(msgPayload); } else { LOG_ERROR("Error decoding protobuf for position message!\n"); diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index da2d9d9055..7a1e9ba490 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -39,6 +39,9 @@ #ifndef HAS_CPU_SHUTDOWN #define HAS_CPU_SHUTDOWN 1 #endif +#ifndef DEFAULT_VREF +#define DEFAULT_VREF 1100 +#endif #if defined(HAS_AXP192) || defined(HAS_AXP2101) #define HAS_PMU @@ -132,4 +135,4 @@ #define RF95_NSS 18 #endif -#define SERIAL0_RX_GPIO 3 // Always GPIO3 on ESP32 +#define SERIAL0_RX_GPIO 3 // Always GPIO3 on ESP32 \ No newline at end of file diff --git a/src/platform/nrf52/main-nrf52.cpp b/src/platform/nrf52/main-nrf52.cpp index 36ddefeb40..c630aa13b7 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 c5a2ecdecf..772e4b1afe 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 af200f9617..5e24bf03c9 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 0000000000..950ceb0cd4 --- /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 0000000000..66344194e1 --- /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 0000000000..b1267d88a6 --- /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 0000000000..4a0b01af2b --- /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 0000000000..cffb924e19 --- /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 0000000000..e88a2790d8 --- /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 dc7adc5ffb..1c021903a1 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 -#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 -} +#define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW #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 d6f073200b..0000000000 --- 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 8ebcb029e4..f57928c60b 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 6b787d320d..e90e3f21bf 100644 --- a/src/power.h +++ b/src/power.h @@ -1,7 +1,10 @@ #pragma once #include "PowerStatus.h" #include "concurrency/OSThread.h" - +#ifdef ARCH_ESP32 +#include +#include +#endif /** * Per @spattinson * MIN_BAT_MILLIVOLTS seems high. Typical 18650 are different chemistry to LiPo, even for LiPos that chart seems a bit off, other @@ -14,6 +17,17 @@ #define BAT_MILLIVOLTS_FULL 4100 #define BAT_MILLIVOLTS_EMPTY 3500 +#ifdef BAT_MEASURE_ADC_UNIT +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 { @@ -34,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(); @@ -45,4 +58,4 @@ class Power : private concurrency::OSThread #endif }; -extern Power *power; +extern Power *power; \ No newline at end of file diff --git a/src/shutdown.h b/src/shutdown.h index b08478a1eb..ee63422dd7 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 e612b00320..5331eaf759 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); @@ -132,6 +132,7 @@ void initDeepSleep() support busted boards, assume button one was pressed wakeButtons = ((uint64_t)1) << buttons.gpios[0]; */ +#ifdef DEBUG_PORT // If we booted because our timer ran out or the user pressed reset, send those as fake events const char *reason = "reset"; // our best guess RESET_REASON hwReason = rtc_get_reset_reason(0); @@ -150,6 +151,7 @@ void initDeepSleep() LOG_INFO("Booted, wake cause %d (boot count %d), reset_reason=%s\n", wakeCause, bootCount, reason); #endif +#endif } bool doPreflightSleep() @@ -250,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 @@ -329,23 +331,27 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r gpio_wakeup_enable((gpio_num_t)PMU_IRQ, GPIO_INTR_LOW_LEVEL); // pmu irq #endif auto res = esp_sleep_enable_gpio_wakeup(); - if (res != ESP_OK) + if (res != ESP_OK) { LOG_DEBUG("esp_sleep_enable_gpio_wakeup result %d\n", res); + } assert(res == ESP_OK); res = esp_sleep_enable_timer_wakeup(sleepUsec); - if (res != ESP_OK) + if (res != ESP_OK) { LOG_DEBUG("esp_sleep_enable_timer_wakeup result %d\n", res); + } assert(res == ESP_OK); res = esp_light_sleep_start(); - if (res != ESP_OK) + if (res != ESP_OK) { LOG_DEBUG("esp_light_sleep_start result %d\n", res); + } assert(res == ESP_OK); esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); #ifdef BUTTON_PIN - if (cause == ESP_SLEEP_WAKEUP_GPIO) + if (cause == ESP_SLEEP_WAKEUP_GPIO) { LOG_INFO("Exit light sleep gpio: btn=%d\n", !digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN)); + } #endif return cause; diff --git a/src/xmodem.h b/src/xmodem.h index 848e926bdb..2ba0bb39f1 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 0dd5198ecf..e2af9aeefa 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/diy/dr-dev/variant.h b/variants/diy/dr-dev/variant.h index 122a617b65..b9c82a9c86 100644 --- a/variants/diy/dr-dev/variant.h +++ b/variants/diy/dr-dev/variant.h @@ -2,6 +2,8 @@ #define HAS_SCREEN 0 #define I2C_SDA 4 #define I2C_SCL 5 +#define BATTERY_PIN 34 +#define ADC_CHANNEL ADC1_GPIO34_CHANNEL // GPS #undef GPS_RX_PIN @@ -67,4 +69,4 @@ #define USE_SX1262 //#define USE_SX1268 //#define USE_LLCC68 -#define SX126X_E22 +#define SX126X_E22 \ No newline at end of file diff --git a/variants/diy/v1/variant.h b/variants/diy/v1/variant.h index da9e415535..a1083f9bb9 100644 --- a/variants/diy/v1/variant.h +++ b/variants/diy/v1/variant.h @@ -9,8 +9,9 @@ #define GPS_TX_PIN 15 #define GPS_UBLOX -#define BUTTON_PIN 39 // The middle button GPIO on the T-Beam -#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +#define BUTTON_PIN 39 // The middle button GPIO on the T-Beam +#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +#define ADC_CHANNEL ADC1_GPIO35_CHANNEL #define ADC_MULTIPLIER 1.85 // (R1 = 470k, R2 = 680k) #define EXT_PWR_DETECT 4 // Pin to detect connected external power source for LILYGO® TTGO T-Energy T18 and other DIY boards #define EXT_NOTIFY_OUT 12 // Overridden default pin to use for Ext Notify Module (#975). @@ -38,9 +39,8 @@ #define SX126X_DIO1 LORA_DIO1 #define SX126X_BUSY LORA_DIO2 #define SX126X_RESET LORA_RESET -//#define SX126X_RXEN 14 -//#define SX126X_TXEN 13 -#define SX126X_POWER_EN (13) +#define SX126X_RXEN RADIOLIB_NC // Defining the RXEN ruins RFSwitching for the E22 900M30S in RadioLib +#define SX126X_TXEN 13 // RX/TX for RFM95/SX127x #define RF95_RXEN 14 @@ -53,4 +53,4 @@ // Internally the TTGO module hooks the SX126x-DIO2 in to control the TX/RX switch // (which is the default for the sx1262interface code) #define SX126X_E22 -#endif +#endif \ No newline at end of file diff --git a/variants/heltec_v1/variant.h b/variants/heltec_v1/variant.h index 948f6ff1e6..d1338a28e6 100644 --- a/variants/heltec_v1/variant.h +++ b/variants/heltec_v1/variant.h @@ -27,3 +27,5 @@ #define ADC_MULTIPLIER 3.2 #define BATTERY_PIN 13 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +#define ADC_CHANNEL ADC2_GPIO13_CHANNEL +#define BAT_MEASURE_ADC_UNIT 2 \ No newline at end of file diff --git a/variants/heltec_v2.1/variant.h b/variants/heltec_v2.1/variant.h index 39a0e677f6..e7cfd5b343 100644 --- a/variants/heltec_v2.1/variant.h +++ b/variants/heltec_v2.1/variant.h @@ -29,5 +29,6 @@ #define ADC_MULTIPLIER 3.8 -#define BATTERY_PIN 37 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage -#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Module. +#define BATTERY_PIN 37 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +#define ADC_CHANNEL ADC1_GPIO37_CHANNEL +#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Module. \ No newline at end of file diff --git a/variants/heltec_v2/variant.h b/variants/heltec_v2/variant.h index 59e0c76e69..5c183818b8 100644 --- a/variants/heltec_v2/variant.h +++ b/variants/heltec_v2/variant.h @@ -27,3 +27,5 @@ // ratio of voltage divider = 3.20 (R12=100k, R10=220k) #define ADC_MULTIPLIER 3.2 #define BATTERY_PIN 13 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +#define ADC_CHANNEL ADC2_GPIO13_CHANNEL +#define BAT_MEASURE_ADC_UNIT 2 \ No newline at end of file diff --git a/variants/heltec_v3/variant.h b/variants/heltec_v3/variant.h index a2e8bde8eb..d9fc0b4c20 100644 --- a/variants/heltec_v3/variant.h +++ b/variants/heltec_v3/variant.h @@ -8,7 +8,9 @@ #define BUTTON_PIN 0 #define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage -#define ADC_MULTIPLIER 5.22 +#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 @@ -27,4 +29,4 @@ #define SX126X_DIO1 LORA_DIO1 #define SX126X_BUSY LORA_DIO2 #define SX126X_RESET LORA_RESET -#define SX126X_E22 +#define SX126X_E22 \ No newline at end of file diff --git a/variants/heltec_wsl_v3/variant.h b/variants/heltec_wsl_v3/variant.h index 66415741b3..0ecc5bea7e 100644 --- a/variants/heltec_wsl_v3/variant.h +++ b/variants/heltec_wsl_v3/variant.h @@ -9,7 +9,9 @@ #define BUTTON_PIN 0 #define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage -#define ADC_MULTIPLIER 5.22 +#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/nano-g1-explorer/variant.h b/variants/nano-g1-explorer/variant.h index ad8957a511..fb3fc72d13 100644 --- a/variants/nano-g1-explorer/variant.h +++ b/variants/nano-g1-explorer/variant.h @@ -29,8 +29,9 @@ // code) #endif -#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +#define ADC_CHANNEL ADC1_GPIO35_CHANNEL #define BATTERY_SENSE_SAMPLES 15 // Set the number of samples, It has an effect of increasing sensitivity. #define ADC_MULTIPLIER 2 -#define USE_SH1107_128_64 +#define USE_SH1107_128_64 \ No newline at end of file diff --git a/variants/rak11310/pins_arduino.h b/variants/rak11310/pins_arduino.h new file mode 100644 index 0000000000..626bed1da8 --- /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 0000000000..a69b18c1a3 --- /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 0000000000..a2bef07304 --- /dev/null +++ b/variants/rak11310/variant.h @@ -0,0 +1,53 @@ +// #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 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 69a77a0292..fe9f062c8e 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 a169e8a9d2..727a1cab66 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 d620a356b4..7e2660aa69 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 6e5c32a529..3228e4c241 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 d620a356b4..4741fd130d 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/station-g1/variant.h b/variants/station-g1/variant.h index 4572d47a66..3439cb1254 100644 --- a/variants/station-g1/variant.h +++ b/variants/station-g1/variant.h @@ -32,7 +32,8 @@ // Info:https://uniteng.com/wiki/doku.php?id=meshtastic:station#rf_design_-_lora_station_edition_g1 #endif -#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +#define ADC_CHANNEL ADC1_GPIO35_CHANNEL #define BATTERY_SENSE_SAMPLES 30 // Set the number of samples, It has an effect of increasing sensitivity. #define ADC_MULTIPLIER 6.45 #define BAT_FULLVOLT 12600 @@ -41,4 +42,4 @@ #define BAT_NOBATVOLT 6690 // different screen -#define USE_SH1106 +#define USE_SH1106 \ No newline at end of file diff --git a/variants/tbeam_v07/variant.h b/variants/tbeam_v07/variant.h index 2c80086889..898705ce29 100644 --- a/variants/tbeam_v07/variant.h +++ b/variants/tbeam_v07/variant.h @@ -6,6 +6,7 @@ #define BUTTON_PIN 39 #define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage #define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Module. +#define ADC_CHANNEL ADC1_GPIO35_CHANNEL #define USE_RF95 #define LORA_DIO0 26 // a No connect on the SX1262 module diff --git a/variants/tlora_t3s3_v1/variant.h b/variants/tlora_t3s3_v1/variant.h index 768a7c2daf..313b08e6d3 100644 --- a/variants/tlora_t3s3_v1/variant.h +++ b/variants/tlora_t3s3_v1/variant.h @@ -9,6 +9,7 @@ #define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage // ratio of voltage divider = 2.0 (R42=100k, R43=100k) #define ADC_MULTIPLIER 2.11 // 2.0 + 10% for correction of display undervoltage. +#define ADC_CHANNEL ADC1_GPIO1_CHANNEL #define I2C_SDA 18 // I2C pins for this board #define I2C_SCL 17 diff --git a/variants/tlora_v1_3/variant.h b/variants/tlora_v1_3/variant.h index 7e8aec0c41..50041f2961 100644 --- a/variants/tlora_v1_3/variant.h +++ b/variants/tlora_v1_3/variant.h @@ -4,6 +4,7 @@ #define GPS_TX_PIN 13 // per @eugene #define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +#define ADC_CHANNEL ADC1_GPIO35_CHANNEL #define I2C_SDA 21 // I2C pins for this board #define I2C_SCL 22 diff --git a/variants/tlora_v2/variant.h b/variants/tlora_v2/variant.h index f18503139f..b9b521771e 100644 --- a/variants/tlora_v2/variant.h +++ b/variants/tlora_v2/variant.h @@ -4,6 +4,7 @@ #define GPS_TX_PIN 13 // per @eugene #define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +#define ADC_CHANNEL ADC1_GPIO35_CHANNEL #define I2C_SDA 21 // I2C pins for this board #define I2C_SCL 22 @@ -19,4 +20,4 @@ #define LORA_DIO0 26 // a No connect on the SX1262 module #define LORA_RESET 14 #define LORA_DIO1 33 // Must be manually wired: https://www.thethingsnetwork.org/forum/t/big-esp32-sx127x-topic-part-3/18436 -#define LORA_DIO2 32 // Not really used +#define LORA_DIO2 32 // Not really used \ No newline at end of file diff --git a/variants/tlora_v2_1_16/variant.h b/variants/tlora_v2_1_16/variant.h index 11c5921ba3..adb5af898c 100644 --- a/variants/tlora_v2_1_16/variant.h +++ b/variants/tlora_v2_1_16/variant.h @@ -3,9 +3,12 @@ #define GPS_RX_PIN 15 // per @der_bear on the forum, 36 is incorrect for this board type and 15 is a better pick #define GPS_TX_PIN 13 -#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +#define BATTERY_PIN 35 +#define ADC_CHANNEL ADC1_GPIO35_CHANNEL +#define BATTERY_SENSE_SAMPLES 30 + // ratio of voltage divider = 2.0 (R42=100k, R43=100k) -#define ADC_MULTIPLIER 2.11 // 2.0 + 10% for correction of display undervoltage. +#define ADC_MULTIPLIER 2 #define I2C_SDA 21 // I2C pins for this board #define I2C_SCL 22 @@ -19,4 +22,4 @@ #define LORA_DIO0 26 // a No connect on the SX1262 module #define LORA_RESET 23 #define LORA_DIO1 33 // https://www.thethingsnetwork.org/forum/t/big-esp32-sx127x-topic-part-3/18436 -#define LORA_DIO2 32 // Not really used +#define LORA_DIO2 32 // Not really used \ No newline at end of file diff --git a/variants/tlora_v2_1_18/variant.h b/variants/tlora_v2_1_18/variant.h index 0262f01223..e8f0a9659d 100644 --- a/variants/tlora_v2_1_18/variant.h +++ b/variants/tlora_v2_1_18/variant.h @@ -4,6 +4,7 @@ #define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage // ratio of voltage divider = 2.0 (R42=100k, R43=100k) #define ADC_MULTIPLIER 2.11 // 2.0 + 10% for correction of display undervoltage. +#define ADC_CHANNEL ADC1_GPIO35_CHANNEL #define I2C_SDA 21 // I2C pins for this board #define I2C_SCL 22 diff --git a/variants/wio-e5/platformio.ini b/variants/wio-e5/platformio.ini index 32436dae8a..07f6efa6df 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 b1f7556b4b..86e58bcb2e 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 0e33ac38b8..c3cd821a8d 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 1 -build = 12 +build = 16