Merge branch 'master' into raspi-portduino

pull/2083/head
Thomas Göttgens 2023-06-27 18:13:24 +02:00 zatwierdzone przez GitHub
commit e878f55ed3
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
110 zmienionych plików z 2607 dodań i 734 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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".

Wyświetl plik

@ -33,6 +33,7 @@ jobs:
- board: m5stack-coreink
- board: tbeam-s3-core
- board: tlora-t3s3-v1
#- board: rak11310
runs-on: ubuntu-latest
steps:
@ -103,16 +104,17 @@ jobs:
with:
board: ${{ matrix.board }}
# build-rpi2040:
# strategy:
# fail-fast: false
# max-parallel: 2
# matrix:
# include:
# - board: pico
# uses: ./.github/workflows/build_rpi2040.yml
# with:
# board: ${{ matrix.board }}
build-rpi2040:
strategy:
fail-fast: false
max-parallel: 2
matrix:
include:
- board: pico
- board: rak11310
uses: ./.github/workflows/build_rpi2040.yml
with:
board: ${{ matrix.board }}
build-native:
runs-on: ubuntu-latest
@ -148,12 +150,14 @@ jobs:
release/device-*.bat
- name: Docker login
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
uses: docker/login-action@v2
with:
username: meshtastic
password: ${{ secrets.DOCKER_TOKEN }}
- name: Docker setup
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
uses: docker/setup-buildx-action@v2
- name: Docker build and push tagged versions
@ -166,7 +170,7 @@ jobs:
tags: meshtastic/device-simulator:${{ steps.version.outputs.version }}
- name: Docker build and push
if: github.ref == 'refs/heads/master'
if: ${{ github.ref == 'refs/heads/master' && github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
uses: docker/build-push-action@v3
with:
context: .
@ -186,7 +190,8 @@ jobs:
gather-artifacts:
runs-on: ubuntu-latest
needs: [build-esp32, build-esp32-s3, build-nrf52, build-native] #, build-rpi2040]
needs:
[build-esp32, build-esp32-s3, build-nrf52, build-native, build-rpi2040]
steps:
- name: Checkout code
uses: actions/checkout@v3

1
.gitignore vendored
Wyświetl plik

@ -30,3 +30,4 @@ __pycache__
venv/
release/
.vscode/extensions.json
/compile_commands.json

Wyświetl plik

@ -37,7 +37,7 @@ lib_deps =
${environmental_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.0
jgromes/RadioLib@^6.0.0
jgromes/RadioLib@^6.1.0
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
@ -55,4 +55,4 @@ lib_ignore =
; customize the partition table
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
board_build.partitions = partition-table.csv
board_build.partitions = partition-table.csv

Wyświetl plik

@ -13,8 +13,7 @@ build_src_filter =
lib_deps=
${arduino_base.lib_deps}
jgromes/RadioLib@^6.0.0
jgromes/RadioLib@^6.1.0
lib_ignore =
BluetoothOTA
BluetoothOTA

Wyświetl plik

@ -22,9 +22,9 @@ lib_deps =
${env.lib_deps}
${networking_base.lib_deps}
rweather/Crypto@^0.4.0
jgromes/RadioLib@^6.0.0
jgromes/RadioLib@6.1.0
build_flags =
${arduino_base.build_flags}
-fPIC
-Isrc/platform/portduino
-Isrc/platform/portduino

Wyświetl plik

@ -1,7 +1,8 @@
; Common settings for rp2040 Processor based targets
[rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#9f8c10e50b5acd18e7bfd32638199c655be73a5b
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#0c33219f53faa035e188925ea1324f472e8b93d2
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.2.2
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
@ -19,5 +20,5 @@ lib_ignore =
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
jgromes/RadioLib@^6.0.0
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
jgromes/RadioLib@^6.1.0
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b

Wyświetl plik

@ -1,20 +1,29 @@
[stm32wl5e_base]
platform = platformio/ststm32@^15.4.1
platform_packages = platformio/framework-arduinoststm32 @ https://github.com/stm32duino/Arduino_Core_STM32.git#6e3f9910d0122e82a6c3438507dfac3d2fd80a39
platform = ststm32
board = generic_wl5e
framework = arduino
build_type = debug
build_flags =
build_flags =
${arduino_base.build_flags}
-Isrc/platform/stm32wl -g
-DconfigUSE_CMSIS_RTOS_V2=1
-DVECT_TAB_OFFSET=0x08000000
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<mqtt/> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<mqtt/> -<graphics> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
board_upload.offset_address = 0x08000000
upload_protocol = stlink
lib_deps =
${env.lib_deps}
jgromes/RadioLib@^6.0.0
jgromes/RadioLib@^6.1.0
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
https://github.com/littlefs-project/littlefs.git#v2.5.1
https://github.com/stm32duino/STM32FreeRTOS.git#10.3.1
lib_ignore =
https://github.com/mathertel/OneButton#2.1.0
https://github.com/mathertel/OneButton#2.1.0

Wyświetl plik

@ -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"

Wyświetl plik

@ -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"
}

Wyświetl plik

@ -2,7 +2,7 @@
; https://docs.platformio.org/page/projectconf.html
[platformio]
default_envs = tbeam
;default_envs = tbeam
;default_envs = pico
;default_envs = tbeam-s3-core
;default_envs = tbeam0.7
@ -25,6 +25,7 @@ default_envs = tbeam
;default_envs = meshtastic-dr-dev
;default_envs = m5stack-coreink
;default_envs = rak4631
default_envs = wio-e5
extra_configs =
arch/*/*.ini
@ -55,6 +56,12 @@ build_flags = -Wno-missing-field-initializers
-DRADIOLIB_EXCLUDE_MORSE
-DRADIOLIB_EXCLUDE_RTTY
-DRADIOLIB_EXCLUDE_SSTV
-DRADIOLIB_EXCLUDE_AX25
-DRADIOLIB_EXCLUDE_DIRECT_RECEIVE
-DRADIOLIB_EXCLUDE_BELL
-DRADIOLIB_EXCLUDE_PAGER
-DRADIOLIB_EXCLUDE_FSK4
-DRADIOLIB_EXCLUDE_APRS
monitor_speed = 115200
@ -102,7 +109,7 @@ lib_deps =
adafruit/Adafruit Unified Sensor@^1.1.9
adafruit/Adafruit BMP280 Library@^2.6.6
adafruit/Adafruit BME280 Library@^2.2.2
boschsensortec/BSEC2 Software Library@^1.3.2200
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.5.2400
boschsensortec/BME68x Sensor Library@^1.1.40407
adafruit/Adafruit MCP9808 Library@^2.0.0
adafruit/Adafruit INA260 Library@^1.5.0

@ -1 +1 @@
Subproject commit d7327c3de2a1dbd9ebb90864c703f97c673a4fc7
Subproject commit 5f3daac5fabdfe2a0561395fed0ba11a38ba3e7e

Wyświetl plik

@ -51,7 +51,7 @@ class ButtonThread : public concurrency::OSThread
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP_SENSE);
#endif
userButton.attachClick(userButtonPressed);
userButton.setClickTicks(300);
userButton.setClickMs(300);
userButton.attachDuringLongPress(userButtonPressedLong);
userButton.attachDoubleClick(userButtonDoublePressed);
userButton.attachMultiClick(userButtonMultiPressed);
@ -157,7 +157,7 @@ class ButtonThread : public concurrency::OSThread
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
#endif
screen->print("Sent ad-hoc ping\n");
service.refreshMyNodeInfo();
service.refreshLocalMeshNode();
service.sendNetworkPing(NODENUM_BROADCAST, true);
}
@ -196,4 +196,4 @@ class ButtonThread : public concurrency::OSThread
}
};
} // namespace concurrency
} // namespace concurrency

Wyświetl plik

@ -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))

Wyświetl plik

@ -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();

Wyświetl plik

@ -55,7 +55,7 @@ class GPSStatus : public Status
#ifdef GPS_EXTRAVERBOSE
LOG_WARN("Using fixed latitude\n");
#endif
meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
return node->position.latitude_i;
} else {
return p.latitude_i;
@ -68,7 +68,7 @@ class GPSStatus : public Status
#ifdef GPS_EXTRAVERBOSE
LOG_WARN("Using fixed longitude\n");
#endif
meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
return node->position.longitude_i;
} else {
return p.longitude_i;
@ -81,7 +81,7 @@ class GPSStatus : public Status
#ifdef GPS_EXTRAVERBOSE
LOG_WARN("Using fixed altitude\n");
#endif
meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
return node->position.altitude;
} else {
return p.altitude;
@ -149,4 +149,4 @@ class GPSStatus : public Status
} // namespace meshtastic
extern meshtastic::GPSStatus *gpsStatus;
extern meshtastic::GPSStatus *gpsStatus;

Wyświetl plik

@ -6,7 +6,6 @@
#include "main.h"
#include "sleep.h"
#include "utils.h"
static const char *TAG = "ADCmod";
#ifdef DEBUG_HEAP_MQTT
#include "mqtt/MQTT.h"
@ -31,16 +30,25 @@ RTC_NOINIT_ATTR uint64_t RTC_reg_b;
#endif // BAT_MEASURE_ADC_UNIT
esp_adc_cal_characteristics_t *adc_characs = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t));
#ifndef ADC_ATTENUATION
static const adc_atten_t atten = ADC_ATTEN_DB_11;
#else
static const adc_atten_t atten = ADC_ATTENUATION;
#endif
#endif // BATTERY_PIN && ARCH_ESP32
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO)
INA260Sensor ina260Sensor;
INA219Sensor ina219Sensor;
#endif
#ifdef HAS_PMU
#include "XPowersAXP192.tpp"
#include "XPowersAXP2101.tpp"
#include "XPowersLibInterface.hpp"
XPowersLibInterface *PMU = NULL;
#else
// Copy of the base class defined in axp20x.h.
// I'd rather not inlude axp20x.h as it brings Wire dependency.
class HasBatteryLevel
@ -126,6 +134,13 @@ class AnalogBatteryLevel : public HasBatteryLevel
virtual uint16_t getBattVoltage() override
{
#if defined(HAS_TELEMETRY) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU)
if (hasINA()) {
LOG_DEBUG("Using INA on I2C addr 0x%x for device battery voltage\n", config.power.device_battery_ina_address);
return getINAVoltage();
}
#endif
#ifndef ADC_MULTIPLIER
#define ADC_MULTIPLIER 2.0
#endif
@ -244,6 +259,35 @@ class AnalogBatteryLevel : public HasBatteryLevel
const float fullVolt = BAT_FULLVOLT, emptyVolt = BAT_EMPTYVOLT, chargingVolt = BAT_CHARGINGVOLT, noBatVolt = BAT_NOBATVOLT;
float last_read_value = 0.0;
uint32_t last_read_time_ms = 0;
#if defined(HAS_TELEMETRY) && !defined(ARCH_PORTDUINO)
uint16_t getINAVoltage()
{
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219] == config.power.device_battery_ina_address) {
return ina219Sensor.getBusVoltageMv();
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260] == config.power.device_battery_ina_address) {
return ina260Sensor.getBusVoltageMv();
}
return 0;
}
bool hasINA()
{
if (!config.power.device_battery_ina_address) {
return false;
}
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219] == config.power.device_battery_ina_address) {
if (!ina219Sensor.isInitialized())
return ina219Sensor.runOnce() > 0;
return ina219Sensor.isRunning();
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260] == config.power.device_battery_ina_address) {
if (!ina260Sensor.isInitialized())
return ina260Sensor.runOnce() > 0;
return ina260Sensor.isRunning();
}
return false;
}
#endif
};
AnalogBatteryLevel analogLevel;
@ -292,12 +336,16 @@ bool Power::analogInit()
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_characs);
// show ADC characterization base
if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
ESP_LOGI(TAG, "ADC characterization based on Two Point values stored in eFuse");
LOG_INFO("ADCmod: ADC characterization based on Two Point values stored in eFuse\n");
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
ESP_LOGI(TAG, "ADC characterization based on reference voltage stored in eFuse");
LOG_INFO("ADCmod: ADC characterization based on reference voltage stored in eFuse\n");
} else {
ESP_LOGI(TAG, "ADC characterization based on default reference voltage");
LOG_INFO("ADCmod: ADC characterization based on default reference voltage\n");
}
#if defined(HELTEC_V3) || defined(HELTEC_WSL_V3)
pinMode(37, OUTPUT); // needed for P channel mosfet to work
digitalWrite(37, LOW);
#endif
#endif // ARCH_ESP32
#ifdef ARCH_NRF52
@ -604,82 +652,80 @@ bool Power::axpChipInit()
} else if (PMU->getChipModel() == XPOWERS_AXP2101) {
/*The alternative version of T-Beam 1.1 differs from T-Beam V1.1 in that it uses an AXP2101 power chip*/
#if (HW_VENDOR == meshtastic_HardwareModel_TBEAM)
// Unuse power channel
PMU->disablePowerOutput(XPOWERS_DCDC2);
PMU->disablePowerOutput(XPOWERS_DCDC3);
PMU->disablePowerOutput(XPOWERS_DCDC4);
PMU->disablePowerOutput(XPOWERS_DCDC5);
PMU->disablePowerOutput(XPOWERS_ALDO1);
PMU->disablePowerOutput(XPOWERS_ALDO4);
PMU->disablePowerOutput(XPOWERS_BLDO1);
PMU->disablePowerOutput(XPOWERS_BLDO2);
PMU->disablePowerOutput(XPOWERS_DLDO1);
PMU->disablePowerOutput(XPOWERS_DLDO2);
if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) {
// Unuse power channel
PMU->disablePowerOutput(XPOWERS_DCDC2);
PMU->disablePowerOutput(XPOWERS_DCDC3);
PMU->disablePowerOutput(XPOWERS_DCDC4);
PMU->disablePowerOutput(XPOWERS_DCDC5);
PMU->disablePowerOutput(XPOWERS_ALDO1);
PMU->disablePowerOutput(XPOWERS_ALDO4);
PMU->disablePowerOutput(XPOWERS_BLDO1);
PMU->disablePowerOutput(XPOWERS_BLDO2);
PMU->disablePowerOutput(XPOWERS_DLDO1);
PMU->disablePowerOutput(XPOWERS_DLDO2);
// GNSS RTC PowerVDD 3300mV
PMU->setPowerChannelVoltage(XPOWERS_VBACKUP, 3300);
PMU->enablePowerOutput(XPOWERS_VBACKUP);
// GNSS RTC PowerVDD 3300mV
PMU->setPowerChannelVoltage(XPOWERS_VBACKUP, 3300);
PMU->enablePowerOutput(XPOWERS_VBACKUP);
// ESP32 VDD 3300mV
// ! No need to set, automatically open , Don't close it
// PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300);
// PMU->setProtectedChannel(XPOWERS_DCDC1);
// ESP32 VDD 3300mV
// ! No need to set, automatically open , Don't close it
// PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300);
// PMU->setProtectedChannel(XPOWERS_DCDC1);
// LoRa VDD 3300mV
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO2);
// LoRa VDD 3300mV
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO2);
// GNSS VDD 3300mV
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO3);
// GNSS VDD 3300mV
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO3);
} else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) {
// t-beam s3 core
/**
* gnss module power channel
* The default ALDO4 is off, you need to turn on the GNSS power first, otherwise it will be invalid during
* initialization
*/
PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO4);
#elif (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE)
// t-beam s3 core
/**
* gnss module power channel
* The default ALDO4 is off, you need to turn on the GNSS power first, otherwise it will be invalid during
* initialization
*/
PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO4);
// lora radio power channel
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO3);
// lora radio power channel
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO3);
// m.2 interface
PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300);
PMU->enablePowerOutput(XPOWERS_DCDC3);
// m.2 interface
PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300);
PMU->enablePowerOutput(XPOWERS_DCDC3);
/**
* ALDO2 cannot be turned off.
* It is a necessary condition for sensor communication.
* It must be turned on to properly access the sensor and screen
* It is also responsible for the power supply of PCF8563
*/
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO2);
/**
* ALDO2 cannot be turned off.
* It is a necessary condition for sensor communication.
* It must be turned on to properly access the sensor and screen
* It is also responsible for the power supply of PCF8563
*/
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO2);
// 6-axis , magnetometer ,bme280 , oled screen power channel
PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO1);
// 6-axis , magnetometer ,bme280 , oled screen power channel
PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO1);
// sdcard power channle
PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300);
PMU->enablePowerOutput(XPOWERS_BLDO1);
// sdcard power channle
PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300);
PMU->enablePowerOutput(XPOWERS_BLDO1);
// PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 3300);
// PMU->enablePowerOutput(XPOWERS_DCDC4);
// PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 3300);
// PMU->enablePowerOutput(XPOWERS_DCDC4);
// not use channel
PMU->disablePowerOutput(XPOWERS_DCDC2); // not elicited
PMU->disablePowerOutput(XPOWERS_DCDC5); // not elicited
PMU->disablePowerOutput(XPOWERS_DLDO1); // Invalid power channel, it does not exist
PMU->disablePowerOutput(XPOWERS_DLDO2); // Invalid power channel, it does not exist
PMU->disablePowerOutput(XPOWERS_VBACKUP);
#endif
// not use channel
PMU->disablePowerOutput(XPOWERS_DCDC2); // not elicited
PMU->disablePowerOutput(XPOWERS_DCDC5); // not elicited
PMU->disablePowerOutput(XPOWERS_DLDO1); // Invalid power channel, it does not exist
PMU->disablePowerOutput(XPOWERS_DLDO2); // Invalid power channel, it does not exist
PMU->disablePowerOutput(XPOWERS_VBACKUP);
}
// disable all axp chip interrupt
PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ);

Wyświetl plik

@ -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");

Wyświetl plik

@ -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) {

Wyświetl plik

@ -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) {

Wyświetl plik

@ -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);
}
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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);

Wyświetl plik

@ -12,7 +12,7 @@
#include <freertos/task.h>
#endif
#if defined(ARDUINO_NRF52_ADAFRUIT)
#if defined(ARDUINO_NRF52_ADAFRUIT) || defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_RP2040)
#define HAS_FREE_RTOS
#include <FreeRTOS.h>
@ -44,4 +44,4 @@ typedef uint32_t BaseType_t;
enum eNotifyAction { eNoAction, eSetValueWithoutOverwrite, eSetValueWithOverwrite };
#endif
#endif

Wyświetl plik

@ -18,10 +18,11 @@
* -------------------------------------------
*/
uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const char *name)
uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_PositionLite &pos, const char *name, bool isCaltopoMode)
{
GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude);
uint32_t len = snprintf(buf, bufsz, "$GNWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", geoCoord.getDMSLatDeg(),
char type = isCaltopoMode ? 'P' : 'N';
uint32_t len = snprintf(buf, bufsz, "$G%cWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", type, geoCoord.getDMSLatDeg(),
(abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6, geoCoord.getDMSLatCP(),
geoCoord.getDMSLonDeg(), (abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6,
geoCoord.getDMSLonCP(), name);
@ -33,6 +34,21 @@ uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const
return len;
}
uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const char *name, bool isCaltopoMode)
{
GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude);
char type = isCaltopoMode ? 'P' : 'N';
uint32_t len = snprintf(buf, bufsz, "$G%cWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", type, geoCoord.getDMSLatDeg(),
(abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6, geoCoord.getDMSLatCP(),
geoCoord.getDMSLonDeg(), (abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6,
geoCoord.getDMSLonCP(), name);
uint32_t chk = 0;
for (uint32_t i = 1; i < len; i++) {
chk ^= buf[i];
}
len += snprintf(buf + len, bufsz - len, "*%02X\r\n", chk);
return len;
}
/* -------------------------------------------
* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
* | | | | | | | | | | | | | | |

Wyświetl plik

@ -3,5 +3,6 @@
#include "main.h"
#include <Arduino.h>
uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const char *name);
uint32_t printGGA(char *buf, size_t bufsz, const meshtastic_Position &pos);
uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const char *name, bool isCaltopoMode = false);
uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_PositionLite &pos, const char *name, bool isCaltopoMode = false);
uint32_t printGGA(char *buf, size_t bufsz, const meshtastic_Position &pos);

Wyświetl plik

@ -0,0 +1,7 @@
#include "main.h"
#ifdef RAK4630
#include <NCP5623.h>
extern NCP5623 rgb;
#endif

Wyświetl plik

@ -27,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "GPS.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "error.h"
#include "gps/GeoCoord.h"
#include "gps/RTC.h"
#include "graphics/images.h"
@ -352,7 +353,7 @@ static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *sta
display->setFont(FONT_MEDIUM);
char tempBuf[24];
snprintf(tempBuf, sizeof(tempBuf), "Critical fault #%d", myNodeInfo.error_code);
snprintf(tempBuf, sizeof(tempBuf), "Critical fault #%d", error_code);
display->drawString(0 + x, 0 + y, tempBuf);
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_SMALL);
@ -372,7 +373,7 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
static char tempBuf[237];
meshtastic_MeshPacket &mp = devicestate.rx_text_message;
meshtastic_NodeInfo *node = nodeDB.getNode(getFrom(&mp));
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp));
// LOG_DEBUG("drawing text message from 0x%x: %s\n", mp.from,
// mp.decoded.variant.data.decoded.bytes);
@ -410,7 +411,7 @@ static void drawWaypointFrame(OLEDDisplay *display, OLEDDisplayUiState *state, i
static char tempBuf[237];
meshtastic_MeshPacket &mp = devicestate.rx_waypoint;
meshtastic_NodeInfo *node = nodeDB.getNode(getFrom(&mp));
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp));
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_SMALL);
@ -711,13 +712,6 @@ static float estimatedHeading(double lat, double lon)
return b;
}
/// Sometimes we will have Position objects that only have a time, so check for
/// valid lat/lon
static bool hasPosition(meshtastic_NodeInfo *n)
{
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
}
static uint16_t getCompassDiam(OLEDDisplay *display)
{
uint16_t diam = 0;
@ -799,16 +793,16 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
if (state->currentFrame != prevFrame) {
prevFrame = state->currentFrame;
nodeIndex = (nodeIndex + 1) % nodeDB.getNumNodes();
meshtastic_NodeInfo *n = nodeDB.getNodeByIndex(nodeIndex);
nodeIndex = (nodeIndex + 1) % nodeDB.getNumMeshNodes();
meshtastic_NodeInfoLite *n = nodeDB.getMeshNodeByIndex(nodeIndex);
if (n->num == nodeDB.getNodeNum()) {
// Don't show our node, just skip to next
nodeIndex = (nodeIndex + 1) % nodeDB.getNumNodes();
n = nodeDB.getNodeByIndex(nodeIndex);
nodeIndex = (nodeIndex + 1) % nodeDB.getNumMeshNodes();
n = nodeDB.getMeshNodeByIndex(nodeIndex);
}
}
meshtastic_NodeInfo *node = nodeDB.getNodeByIndex(nodeIndex);
meshtastic_NodeInfoLite *node = nodeDB.getMeshNodeByIndex(nodeIndex);
display->setFont(FONT_SMALL);
@ -842,7 +836,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
static char distStr[20];
strncpy(distStr, "? km", sizeof(distStr)); // might not have location data
meshtastic_NodeInfo *ourNode = nodeDB.getNode(nodeDB.getNodeNum());
meshtastic_NodeInfoLite *ourNode = nodeDB.getMeshNode(nodeDB.getNodeNum());
const char *fields[] = {username, distStr, signalStr, lastStr, NULL};
int16_t compassX = 0, compassY = 0;
@ -856,15 +850,15 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
}
bool hasNodeHeading = false;
if (ourNode && hasPosition(ourNode)) {
meshtastic_Position &op = ourNode->position;
if (ourNode && hasValidPosition(ourNode)) {
meshtastic_PositionLite &op = ourNode->position;
float myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
drawCompassNorth(display, compassX, compassY, myHeading);
if (hasPosition(node)) {
if (hasValidPosition(node)) {
// display direction toward node
hasNodeHeading = true;
meshtastic_Position &p = node->position;
meshtastic_PositionLite &p = node->position;
float d =
GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
@ -892,7 +886,8 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
if (!hasNodeHeading) {
// direction to node is unknown so display question mark
// Debug info for gps lock errors
// LOG_DEBUG("ourNode %d, ourPos %d, theirPos %d\n", !!ourNode, ourNode && hasPosition(ourNode), hasPosition(node));
// LOG_DEBUG("ourNode %d, ourPos %d, theirPos %d\n", !!ourNode, ourNode && hasValidPosition(ourNode),
// hasValidPosition(node));
display->drawString(compassX - FONT_HEIGHT_SMALL / 4, compassY - FONT_HEIGHT_SMALL / 2, "?");
}
display->drawCircle(compassX, compassY, getCompassDiam(display) / 2);
@ -1245,9 +1240,9 @@ void Screen::setFrames()
#endif
// We don't show the node info our our node (if we have it yet - we should)
size_t numnodes = nodeDB.getNumNodes();
if (numnodes > 0)
numnodes--;
size_t numMeshNodes = nodeDB.getNumMeshNodes();
if (numMeshNodes > 0)
numMeshNodes--;
size_t numframes = 0;
@ -1264,7 +1259,7 @@ void Screen::setFrames()
LOG_DEBUG("Added modules. numframes: %d\n", numframes);
// If we have a critical fault, show it first
if (myNodeInfo.error_code)
if (error_code)
normalFrames[numframes++] = drawCriticalFaultFrame;
// If we have a text message - show it next, unless it's a phone message and we aren't using any special modules
@ -1278,7 +1273,7 @@ void Screen::setFrames()
// then all the nodes
// We only show a few nodes in our scrolling list - because meshes with many nodes would have too many screens
size_t numToShow = min(numnodes, 4U);
size_t numToShow = min(numMeshNodes, 4U);
for (size_t i = 0; i < numToShow; i++)
normalFrames[numframes++] = drawNodeInfo;
@ -1855,4 +1850,4 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
} // namespace graphics
#else
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
#endif // HAS_SCREEN
#endif // HAS_SCREEN

Wyświetl plik

@ -19,6 +19,7 @@
#include "detect/ScanI2CTwoWire.h"
#include "detect/axpDebug.h"
#include "detect/einkScan.h"
#include "graphics/RAKled.h"
#include "graphics/Screen.h"
#include "main.h"
#include "mesh/generated/meshtastic/config.pb.h"
@ -59,6 +60,9 @@ NRF52Bluetooth *nrf52Bluetooth;
#include "SX1262Interface.h"
#include "SX1268Interface.h"
#include "SX1280Interface.h"
#ifdef ARCH_STM32WL
#include "STM32WLE5JCInterface.h"
#endif
#if !HAS_RADIO && defined(ARCH_PORTDUINO)
#include "platform/portduino/SimRadio.h"
#endif
@ -68,7 +72,7 @@ NRF52Bluetooth *nrf52Bluetooth;
#endif
#include "PowerFSMThread.h"
#if !defined(ARCH_PORTDUINO)
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#include "AccelerometerThread.h"
#endif
@ -260,6 +264,12 @@ void setup()
// We need to enable 3.3V periphery in order to scan it
pinMode(PIN_3V3_EN, OUTPUT);
digitalWrite(PIN_3V3_EN, HIGH);
#ifndef USE_EINK
// RAK-12039 set pin for Air quality sensor
pinMode(AQ_SET_PIN, OUTPUT);
digitalWrite(AQ_SET_PIN, HIGH);
#endif
#endif
// Currently only the tbeam has a PMU
@ -347,10 +357,20 @@ void setup()
* nodeTelemetrySensorsMap singleton. This wraps that logic in a temporary scope to declare the temporary field
* "found".
*/
// Only one supported RGB LED currently
rgb_found = i2cScanner->find(ScanI2C::DeviceType::NCP5623);
#if !defined(ARCH_PORTDUINO)
// Start the RGB LED at 50%
#ifdef RAK4630
if (rgb_found.type == ScanI2C::NCP5623) {
rgb.begin();
rgb.setCurrent(10);
rgb.setColor(128, 128, 128);
}
#endif
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
auto acc_info = i2cScanner->firstAccelerometer();
accelerometer_found = acc_info.type != ScanI2C::DeviceType::NONE ? acc_info.address : accelerometer_found;
LOG_DEBUG("acc_info = %i\n", acc_info.type);
@ -439,7 +459,7 @@ void setup()
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // keep dimension of 128x64
#endif
#if !defined(ARCH_PORTDUINO)
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
if (acc_info.type != ScanI2C::DeviceType::NONE) {
accelerometerThread = new AccelerometerThread(acc_info.type);
}
@ -447,7 +467,21 @@ void setup()
// Init our SPI controller (must be before screen and lora)
initSPI();
#ifndef ARCH_ESP32
#ifdef ARCH_RP2040
#ifdef HW_SPI1_DEVICE
SPI1.setSCK(RF95_SCK);
SPI1.setTX(RF95_MOSI);
SPI1.setRX(RF95_MISO);
pinMode(RF95_NSS, OUTPUT);
digitalWrite(RF95_NSS, HIGH);
SPI1.begin(false);
#else // HW_SPI1_DEVICE
SPI.setSCK(RF95_SCK);
SPI.setTX(RF95_MOSI);
SPI.setRX(RF95_MISO);
SPI.begin(false);
#endif // HW_SPI1_DEVICE
#elif !defined(ARCH_ESP32) // ARCH_RP2040
SPI.begin();
#else
// ESP32
@ -509,11 +543,25 @@ void setup()
digitalWrite(SX126X_ANT_SW, 1);
#endif
// Init LockingHAL first, to use it for radio init
#ifdef HW_SPI1_DEVICE
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI1, spiSettings);
#else // HW_SPI1_DEVICE
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
#endif
// radio init MUST BE AFTER service.init, so we have our radio config settings (from nodedb init)
#if defined(USE_STM32WLx)
if (!rIf) {
rIf = new STM32WLE5JCInterface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
if (!rIf->init()) {
LOG_WARN("Failed to find STM32WL radio\n");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("STM32WL Radio init succeeded, using STM32WL radio\n");
}
}
#endif
#if !HAS_RADIO && defined(ARCH_PORTDUINO)
if (!rIf) {
@ -635,12 +683,10 @@ void setup()
else {
router->addInterface(rIf);
// Calculate and save the bit rate to myNodeInfo
// TODO: This needs to be added what ever method changes the channel from the phone.
myNodeInfo.bitrate =
(float(meshtastic_Constants_DATA_PAYLOAD_LEN) / (float(rIf->getPacketTime(meshtastic_Constants_DATA_PAYLOAD_LEN)))) *
1000;
LOG_DEBUG("myNodeInfo.bitrate = %f bytes / sec\n", myNodeInfo.bitrate);
// Log bit rate to debug output
LOG_DEBUG("LoRA bitrate = %f bytes / sec\n", (float(meshtastic_Constants_DATA_PAYLOAD_LEN) /
(float(rIf->getPacketTime(meshtastic_Constants_DATA_PAYLOAD_LEN)))) *
1000);
}
// This must be _after_ service.init because we need our preferences loaded from flash to have proper timeout values
@ -661,7 +707,7 @@ bool runASAP;
extern meshtastic_DeviceMetadata getDeviceMetadata()
{
meshtastic_DeviceMetadata deviceMetadata;
strncpy(deviceMetadata.firmware_version, myNodeInfo.firmware_version, 18);
strncpy(deviceMetadata.firmware_version, optstr(APP_VERSION), sizeof(deviceMetadata.firmware_version));
deviceMetadata.device_state_version = DEVICESTATE_CUR_VER;
deviceMetadata.canShutdown = pmu_found || HAS_CPU_SHUTDOWN;
deviceMetadata.hasBluetooth = HAS_BLUETOOTH;
@ -718,4 +764,4 @@ void loop()
mainDelay.delay(delayMsec);
}
// if (didWake) LOG_DEBUG("wake!\n");
}
}

Wyświetl plik

@ -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;

Wyświetl plik

@ -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);
}
}

Wyświetl plik

@ -10,6 +10,9 @@ template class SX126xInterface<SX1262>;
template class SX126xInterface<SX1268>;
template class SX126xInterface<LLCC68>;
template class SX128xInterface<SX1280>;
#ifdef ARCH_STM32WL
template class SX126xInterface<STM32WLx>;
#endif
#if HAS_ETHERNET
#include "api/ethServerAPI.h"

Wyświetl plik

@ -9,6 +9,7 @@
#include "NodeDB.h"
#include "PowerFSM.h"
#include "RTC.h"
#include "TypeConversions.h"
#include "main.h"
#include "mesh-pb-constants.h"
#include "modules/NodeInfoModule.h"
@ -76,7 +77,8 @@ int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp)
powerFSM.trigger(EVENT_PACKET_FOR_PHONE); // Possibly keep the node from sleeping
nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB.getNode(mp->from)->has_user && nodeInfoModule) {
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB.getMeshNode(mp->from)->has_user &&
nodeInfoModule) {
LOG_INFO("Heard a node on channel %d we don't know, sending NodeInfo and asking for a response.\n", mp->channel);
nodeInfoModule->sendOurNodeInfo(mp->from, true, mp->channel);
}
@ -236,10 +238,11 @@ void MeshService::sendToMesh(meshtastic_MeshPacket *p, RxSource src, bool ccToPh
void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
{
meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
assert(node);
if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) {
if (hasValidPosition(node)) {
if (positionModule) {
LOG_INFO("Sending position ping to 0x%x, wantReplies=%d, channel=%d\n", dest, wantReplies, node->channel);
positionModule->sendOurPosition(dest, wantReplies, node->channel);
@ -266,9 +269,9 @@ void MeshService::sendToPhone(meshtastic_MeshPacket *p)
fromNum++;
}
meshtastic_NodeInfo *MeshService::refreshMyNodeInfo()
meshtastic_NodeInfoLite *MeshService::refreshLocalMeshNode()
{
meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
assert(node);
// We might not have a position yet for our local node, in that case, at least try to send the time
@ -277,7 +280,7 @@ meshtastic_NodeInfo *MeshService::refreshMyNodeInfo()
node->has_position = true;
}
meshtastic_Position &position = node->position;
meshtastic_PositionLite &position = node->position;
// Update our local node info with our time (even if we don't decide to update anyone else)
node->last_heard =
@ -293,7 +296,7 @@ meshtastic_NodeInfo *MeshService::refreshMyNodeInfo()
int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
{
// Update our local node info with our position (even if we don't decide to update anyone else)
meshtastic_NodeInfo *node = refreshMyNodeInfo();
meshtastic_NodeInfoLite *node = refreshLocalMeshNode();
meshtastic_Position pos = meshtastic_Position_init_default;
if (newStatus->getHasLock()) {
@ -307,12 +310,12 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
#endif
if (config.position.fixed_position) {
LOG_WARN("Using fixed position\n");
pos = node->position;
pos = ConvertToPosition(node->position);
}
}
// Finally add a fresh timestamp and battery level reading
// I KNOW this is redundant with refreshMyNodeInfo() above, but these are
// I KNOW this is redundant with refreshLocalMeshNode() above, but these are
// inexpensive nonblocking calls and can be refactored in due course
pos.time = getValidTime(RTCQualityGPS);
@ -329,4 +332,4 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
bool MeshService::isToPhoneQueueEmpty()
{
return toPhoneQueue.isEmpty();
}
}

Wyświetl plik

@ -98,7 +98,7 @@ class MeshService
bool cancelSending(PacketId id);
/// Pull the latest power and time info into my nodeinfo
meshtastic_NodeInfo *refreshMyNodeInfo();
meshtastic_NodeInfoLite *refreshLocalMeshNode();
/// Send a packet to the phone
void sendToPhone(meshtastic_MeshPacket *p);
@ -118,4 +118,4 @@ class MeshService
ErrorCode sendQueueStatusToPhone(const meshtastic_QueueStatus &qs, ErrorCode res, uint32_t mesh_packet_id);
};
extern MeshService service;
extern MeshService service;

Wyświetl plik

@ -11,6 +11,7 @@
#include "PowerFSM.h"
#include "RTC.h"
#include "Router.h"
#include "TypeConversions.h"
#include "error.h"
#include "main.h"
#include "mesh-pb-constants.h"
@ -55,10 +56,18 @@ extern void getMacAddr(uint8_t *dmac);
* we use !macaddr (no colons).
*/
meshtastic_User &owner = devicestate.owner;
meshtastic_Position localPosition = meshtastic_Position_init_default;
meshtastic_CriticalErrorCode error_code =
meshtastic_CriticalErrorCode_NONE; // For the error code, only show values from this boot (discard value from flash)
uint32_t error_address = 0;
static uint8_t ourMacAddr[6];
NodeDB::NodeDB() : nodes(devicestate.node_db), numNodes(&devicestate.node_db_count) {}
NodeDB::NodeDB()
: nodes(devicestate.node_db), numNodes(&devicestate.node_db_count), meshNodes(devicestate.node_db_lite),
numMeshNodes(&devicestate.node_db_lite_count)
{
}
/**
* Most (but not always) of the time we want to treat packets 'from' the local phone (where from == 0), as if they originated on
@ -258,6 +267,9 @@ void NodeDB::resetNodes()
{
devicestate.node_db_count = 0;
memset(devicestate.node_db, 0, sizeof(devicestate.node_db));
devicestate.node_db_lite_count = 0;
memset(devicestate.node_db_lite, 0, sizeof(devicestate.node_db_lite));
saveDeviceStateToDisk();
}
@ -272,17 +284,12 @@ void NodeDB::installDefaultDeviceState()
devicestate.has_my_node = true;
devicestate.has_owner = true;
devicestate.node_db_count = 0;
devicestate.node_db_lite_count = 0;
devicestate.version = DEVICESTATE_CUR_VER;
devicestate.receive_queue_count = 0; // Not yet implemented FIXME
// default to no GPS, until one has been found by probing
myNodeInfo.has_gps = false;
myNodeInfo.message_timeout_msec = FLOOD_EXPIRE_TIME;
generatePacketId(); // FIXME - ugly way to init current_packet_id;
// Init our blank owner info to reasonable defaults
getMacAddr(ourMacAddr);
// Set default owner name
pickNewNodeNum(); // based on macaddr now
snprintf(owner.long_name, sizeof(owner.long_name), "Meshtastic %02x%02x", ourMacAddr[4], ourMacAddr[5]);
@ -303,28 +310,34 @@ void NodeDB::init()
int saveWhat = 0;
myNodeInfo.max_channels = MAX_NUM_CHANNELS; // tell others the max # of channels we can understand
myNodeInfo.error_code =
meshtastic_CriticalErrorCode_NONE; // For the error code, only show values from this boot (discard value from flash)
myNodeInfo.error_address = 0;
// likewise - we always want the app requirements to come from the running appload
myNodeInfo.min_app_version = 20300; // format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20
myNodeInfo.min_app_version = 20300; // format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20
myNodeInfo.max_channels = MAX_NUM_CHANNELS; // tell others the max # of channels we can understand
// Note! We do this after loading saved settings, so that if somehow an invalid nodenum was stored in preferences we won't
// keep using that nodenum forever. Crummy guess at our nodenum (but we will check against the nodedb to avoid conflicts)
strncpy(myNodeInfo.firmware_version, optstr(APP_VERSION), sizeof(myNodeInfo.firmware_version));
pickNewNodeNum();
// Set our board type so we can share it with others
owner.hw_model = HW_VENDOR;
// Include our owner in the node db under our nodenum
meshtastic_NodeInfo *info = getOrCreateNode(getNodeNum());
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getNodeNum());
info->user = owner;
info->has_user = true;
strncpy(myNodeInfo.firmware_version, optstr(APP_VERSION), sizeof(myNodeInfo.firmware_version));
if (*numNodes > 0) {
LOG_DEBUG("Legacy NodeDB detected... Migrating to NodeDBLite\n");
uint32_t readIndex = 0;
const meshtastic_NodeInfo *oldNodeInfo = nodeDB.readNextNodeInfo(readIndex);
while (oldNodeInfo != NULL) {
migrateToNodeInfoLite(oldNodeInfo);
oldNodeInfo = nodeDB.readNextNodeInfo(readIndex);
}
LOG_DEBUG("Migration complete! Clearing out legacy NodeDB...\n");
devicestate.node_db_count = 0;
memset(devicestate.node_db, 0, sizeof(devicestate.node_db));
}
#ifdef ARCH_ESP32
Preferences preferences;
@ -332,11 +345,6 @@ void NodeDB::init()
myNodeInfo.reboot_count = preferences.getUInt("rebootCounter", 0);
preferences.end();
LOG_DEBUG("Number of Device Reboots: %d\n", myNodeInfo.reboot_count);
/* The ESP32 has a wifi radio. This will need to be modified at some point so
* the test isn't so simplistic.
*/
myNodeInfo.has_wifi = true;
#endif
resetRadioConfig(); // If bogus settings got saved, then fix them
@ -367,17 +375,19 @@ void NodeDB::pickNewNodeNum()
{
NodeNum r = myNodeInfo.my_node_num;
// If we don't have a nodenum at app - pick an initial nodenum based on the macaddr
if (r == 0)
r = (ourMacAddr[2] << 24) | (ourMacAddr[3] << 16) | (ourMacAddr[4] << 8) | ourMacAddr[5];
getMacAddr(ourMacAddr); // Make sure ourMacAddr is set
// Pick an initial nodenum based on the macaddr
r = (ourMacAddr[2] << 24) | (ourMacAddr[3] << 16) | (ourMacAddr[4] << 8) | ourMacAddr[5];
if (r == NODENUM_BROADCAST || r < NUM_RESERVED)
r = NUM_RESERVED; // don't pick a reserved node number
meshtastic_NodeInfo *found;
while ((found = getNode(r)) && memcmp(found->user.macaddr, owner.macaddr, sizeof(owner.macaddr))) {
meshtastic_NodeInfoLite *found;
while ((found = getMeshNode(r)) && memcmp(found->user.macaddr, owner.macaddr, sizeof(owner.macaddr))) {
// FIXME: input for random() is int, so NODENUM_BROADCAST becomes -1
NodeNum n = random(NUM_RESERVED, NODENUM_BROADCAST); // try a new random choice
LOG_DEBUG("NOTE! Our desired nodenum 0x%x is in use, so trying for 0x%x\n", r, n);
LOG_WARN("NOTE! Our desired nodenum 0x%x is in use, so trying for 0x%x\n", r, n);
r = n;
}
@ -584,16 +594,24 @@ void NodeDB::saveToDisk(int saveWhat)
}
}
const meshtastic_NodeInfo *NodeDB::readNextInfo()
const meshtastic_NodeInfo *NodeDB::readNextNodeInfo(uint32_t &readIndex)
{
if (readPointer < *numNodes)
return &nodes[readPointer++];
if (readIndex < *numNodes)
return &nodes[readIndex++];
else
return NULL;
}
const meshtastic_NodeInfoLite *NodeDB::readNextMeshNode(uint32_t &readIndex)
{
if (readIndex < *numMeshNodes)
return &meshNodes[readIndex++];
else
return NULL;
}
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
uint32_t sinceLastSeen(const meshtastic_NodeInfo *n)
uint32_t sinceLastSeen(const meshtastic_NodeInfoLite *n)
{
uint32_t now = getTime();
@ -617,13 +635,13 @@ uint32_t sinceReceived(const meshtastic_MeshPacket *p)
#define NUM_ONLINE_SECS (60 * 60 * 2) // 2 hrs to consider someone offline
size_t NodeDB::getNumOnlineNodes()
size_t NodeDB::getNumOnlineMeshNodes()
{
size_t numseen = 0;
// FIXME this implementation is kinda expensive
for (int i = 0; i < *numNodes; i++)
if (sinceLastSeen(&nodes[i]) < NUM_ONLINE_SECS)
for (int i = 0; i < *numMeshNodes; i++)
if (sinceLastSeen(&meshNodes[i]) < NUM_ONLINE_SECS)
numseen++;
return numseen;
@ -635,7 +653,7 @@ size_t NodeDB::getNumOnlineNodes()
*/
void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSource src)
{
meshtastic_NodeInfo *info = getOrCreateNode(nodeId);
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId);
if (!info) {
return;
}
@ -644,7 +662,9 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou
// Local packet, fully authoritative
LOG_INFO("updatePosition LOCAL pos@%x, time=%u, latI=%d, lonI=%d, alt=%d\n", p.timestamp, p.time, p.latitude_i,
p.longitude_i, p.altitude);
info->position = p;
info->position = ConvertToPositionLite(p);
localPosition = p;
} else if ((p.time > 0) && !p.latitude_i && !p.longitude_i && !p.timestamp && !p.location_source) {
// FIXME SPECIAL TIME SETTING PACKET FROM EUD TO RADIO
// (stop-gap fix for issue #900)
@ -662,7 +682,7 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou
uint32_t tmp_time = info->position.time;
// Next, update atomically
info->position = p;
info->position = ConvertToPositionLite(p);
// Last, restore any fields that may have been overwritten
if (!info->position.time)
@ -678,7 +698,7 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou
*/
void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxSource src)
{
meshtastic_NodeInfo *info = getOrCreateNode(nodeId);
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId);
// Environment metrics should never go to NodeDb but we'll safegaurd anyway
if (!info || t.which_variant != meshtastic_Telemetry_device_metrics_tag) {
return;
@ -700,7 +720,7 @@ void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxS
*/
bool NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p)
{
meshtastic_NodeInfo *info = getOrCreateNode(nodeId);
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId);
if (!info) {
return false;
}
@ -733,7 +753,7 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.from) {
LOG_DEBUG("Update DB node 0x%x, rx_time=%u, channel=%d\n", mp.from, mp.rx_time, mp.channel);
meshtastic_NodeInfo *info = getOrCreateNode(getFrom(&mp));
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getFrom(&mp));
if (!info) {
return;
}
@ -750,9 +770,9 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
}
}
uint8_t NodeDB::getNodeChannel(NodeNum n)
uint8_t NodeDB::getMeshNodeChannel(NodeNum n)
{
meshtastic_NodeInfo *info = getNode(n);
meshtastic_NodeInfoLite *info = getMeshNode(n);
if (!info) {
return 0; // defaults to PRIMARY
}
@ -761,7 +781,7 @@ uint8_t NodeDB::getNodeChannel(NodeNum n)
/// Find a node in our DB, return null for missing
/// NOTE: This function might be called from an ISR
meshtastic_NodeInfo *NodeDB::getNode(NodeNum n)
meshtastic_NodeInfo *NodeDB::getNodeInfo(NodeNum n)
{
for (int i = 0; i < *numNodes; i++)
if (nodes[i].num == n)
@ -770,38 +790,100 @@ meshtastic_NodeInfo *NodeDB::getNode(NodeNum n)
return NULL;
}
/// Find a node in our DB, create an empty NodeInfo if missing
meshtastic_NodeInfo *NodeDB::getOrCreateNode(NodeNum n)
/// Find a node in our DB, return null for missing
/// NOTE: This function might be called from an ISR
meshtastic_NodeInfoLite *NodeDB::getMeshNode(NodeNum n)
{
meshtastic_NodeInfo *info = getNode(n);
for (int i = 0; i < *numMeshNodes; i++)
if (meshNodes[i].num == n)
return &meshNodes[i];
if (!info) {
if ((*numNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfo_size * 3)) {
screen->print("warning: node_db full! erasing oldest entry\n");
return NULL;
}
/// Find a node in our DB, create an empty NodeInfo if missing
meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
{
meshtastic_NodeInfoLite *lite = getMeshNode(n);
if (!lite) {
if ((*numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfoLite_size * 3)) {
screen->print("warning: node_db_lite full! erasing oldest entry\n");
// look for oldest node and erase it
uint32_t oldest = UINT32_MAX;
int oldestIndex = -1;
for (int i = 0; i < *numNodes; i++) {
if (nodes[i].last_heard < oldest) {
oldest = nodes[i].last_heard;
for (int i = 0; i < *numMeshNodes; i++) {
if (meshNodes[i].last_heard < oldest) {
oldest = meshNodes[i].last_heard;
oldestIndex = i;
}
}
// Shove the remaining nodes down the chain
for (int i = oldestIndex; i < *numNodes - 1; i++) {
nodes[i] = nodes[i + 1];
for (int i = oldestIndex; i < *numMeshNodes - 1; i++) {
meshNodes[i] = meshNodes[i + 1];
}
(*numNodes)--;
(*numMeshNodes)--;
}
// add the node at the end
info = &nodes[(*numNodes)++];
lite = &meshNodes[(*numMeshNodes)++];
// everything is missing except the nodenum
memset(info, 0, sizeof(*info));
info->num = n;
memset(lite, 0, sizeof(*lite));
lite->num = n;
}
return info;
return lite;
}
void NodeDB::migrateToNodeInfoLite(const meshtastic_NodeInfo *node)
{
meshtastic_NodeInfoLite *lite = getMeshNode(node->num);
if (!lite) {
if ((*numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfoLite_size * 3)) {
screen->print("warning: node_db_lite full! erasing oldest entry\n");
// look for oldest node and erase it
uint32_t oldest = UINT32_MAX;
int oldestIndex = -1;
for (int i = 0; i < *numMeshNodes; i++) {
if (meshNodes[i].last_heard < oldest) {
oldest = meshNodes[i].last_heard;
oldestIndex = i;
}
}
// Shove the remaining nodes down the chain
for (int i = oldestIndex; i < *numMeshNodes - 1; i++) {
meshNodes[i] = meshNodes[i + 1];
}
(*numMeshNodes)--;
}
// add the node at the end
lite = &meshNodes[(*numMeshNodes)++];
// everything is missing except the nodenum
memset(lite, 0, sizeof(*lite));
lite->num = node->num;
lite->snr = node->snr;
lite->last_heard = node->last_heard;
lite->channel = node->channel;
if (node->has_position) {
lite->has_position = true;
lite->position.latitude_i = node->position.latitude_i;
lite->position.longitude_i = node->position.longitude_i;
lite->position.altitude = node->position.altitude;
lite->position.location_source = node->position.location_source;
lite->position.time = node->position.time;
}
if (node->has_user) {
lite->has_user = true;
lite->user = node->user;
}
if (node->has_device_metrics) {
lite->has_device_metrics = true;
lite->device_metrics = node->device_metrics;
}
}
}
/// Record an error that should be reported via analytics
@ -817,13 +899,12 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co
}
// Record error to DB
myNodeInfo.error_code = code;
myNodeInfo.error_address = address;
myNodeInfo.error_count++;
error_code = code;
error_address = address;
// Currently portuino is mostly used for simulation. Make sue the user notices something really bad happend
#ifdef ARCH_PORTDUINO
LOG_ERROR("A critical failure occurred, portduino is exiting...");
exit(2);
#endif
}
}

Wyświetl plik

@ -7,6 +7,7 @@
#include "MeshTypes.h"
#include "NodeStatus.h"
#include "mesh-pb-constants.h"
#include "mesh/generated/meshtastic/mesh.pb.h" // For CriticalErrorCode
/*
DeviceState versions used to be defined in the .proto file but really only this function cares. So changed to a
@ -28,9 +29,10 @@ extern meshtastic_LocalConfig config;
extern meshtastic_LocalModuleConfig moduleConfig;
extern meshtastic_OEMStore oemStore;
extern meshtastic_User &owner;
extern meshtastic_Position localPosition;
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
uint32_t sinceLastSeen(const meshtastic_NodeInfo *n);
uint32_t sinceLastSeen(const meshtastic_NodeInfoLite *n);
/// Given a packet, return how many seconds in the past (vs now) it was received
uint32_t sinceReceived(const meshtastic_MeshPacket *p);
@ -46,11 +48,12 @@ class NodeDB
meshtastic_NodeInfo *nodes;
pb_size_t *numNodes;
uint32_t readPointer = 0;
meshtastic_NodeInfoLite *meshNodes;
pb_size_t *numMeshNodes;
public:
bool updateGUI = false; // we think the gui should definitely be redrawn, screen will clear this once handled
meshtastic_NodeInfo *updateGUIforNode = NULL; // if currently showing this node, we think you should update the GUI
meshtastic_NodeInfoLite *updateGUIforNode = NULL; // if currently showing this node, we think you should update the GUI
Observable<const meshtastic::NodeStatus *> newStatus;
/// don't do mesh based algoritm for node id assignment (initially)
@ -91,8 +94,6 @@ class NodeDB
/// @return our node number
NodeNum getNodeNum() { return myNodeInfo.my_node_num; }
size_t getNumNodes() { return *numNodes; }
/// if returns false, that means our node should send a DenyNodeNum response. If true, we think the number is okay for use
// bool handleWantNodeNum(NodeNum n);
@ -104,29 +105,14 @@ class NodeDB
their denial?)
*/
/// Called from bluetooth when the user wants to start reading the node DB from scratch.
void resetReadPointer() { readPointer = 0; }
/// Allow the bluetooth layer to read our next nodeinfo record, or NULL if done reading
const meshtastic_NodeInfo *readNextInfo();
/// pick a provisional nodenum we hope no one is using
void pickNewNodeNum();
// get channel channel index we heard a nodeNum on, defaults to 0 if not found
uint8_t getNodeChannel(NodeNum n);
/// Find a node in our DB, return null for missing
meshtastic_NodeInfo *getNode(NodeNum n);
meshtastic_NodeInfo *getNodeByIndex(size_t x)
{
assert(x < *numNodes);
return &nodes[x];
}
uint8_t getMeshNodeChannel(NodeNum n);
/// Return the number of nodes we've heard from recently (within the last 2 hrs?)
size_t getNumOnlineNodes();
size_t getNumOnlineMeshNodes();
void initConfigIntervals(), initModuleConfigIntervals(), resetNodes();
@ -137,15 +123,38 @@ class NodeDB
void installRoleDefaults(meshtastic_Config_DeviceConfig_Role role);
const meshtastic_NodeInfoLite *readNextMeshNode(uint32_t &readIndex);
meshtastic_NodeInfoLite *getMeshNodeByIndex(size_t x)
{
assert(x < *numMeshNodes);
return &meshNodes[x];
}
meshtastic_NodeInfoLite *getMeshNode(NodeNum n);
size_t getNumMeshNodes() { return *numMeshNodes; }
private:
/// Find a node in our DB, create an empty NodeInfo if missing
meshtastic_NodeInfo *getOrCreateNode(NodeNum n);
/// Find a node in our DB, create an empty NodeInfoLite if missing
meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n);
void migrateToNodeInfoLite(const meshtastic_NodeInfo *node);
/// Find a node in our DB, return null for missing
meshtastic_NodeInfo *getNodeInfo(NodeNum n);
/// Allow the bluetooth layer to read our next nodeinfo record, or NULL if done reading
const meshtastic_NodeInfo *readNextNodeInfo(uint32_t &readIndex);
size_t getNumNodes() { return *numNodes; }
meshtastic_NodeInfo *getNodeByIndex(size_t x)
{
assert(x < *numNodes);
return &nodes[x];
}
/// Notify observers of changes to the DB
void notifyObservers(bool forceUpdate = false)
{
// Notify observers of the current node state
const meshtastic::NodeStatus status = meshtastic::NodeStatus(getNumOnlineNodes(), getNumNodes(), forceUpdate);
const meshtastic::NodeStatus status = meshtastic::NodeStatus(getNumOnlineMeshNodes(), getNumMeshNodes(), forceUpdate);
newStatus.notifyObservers(&status);
}
@ -217,12 +226,30 @@ inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t d
return defaultInterval * 1000;
}
/// Sometimes we will have Position objects that only have a time, so check for
/// valid lat/lon
static inline bool hasValidPosition(const meshtastic_NodeInfo *n)
{
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
}
static inline bool hasValidPosition(const meshtastic_NodeInfoLite *n)
{
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
}
/** The current change # for radio settings. Starts at 0 on boot and any time the radio settings
* might have changed is incremented. Allows others to detect they might now be on a new channel.
*/
extern uint32_t radioGeneration;
extern meshtastic_CriticalErrorCode error_code;
/*
* A numeric error address (nonzero if available)
*/
extern uint32_t error_address;
#define Module_Config_size \
(ModuleConfig_CannedMessageConfig_size + ModuleConfig_ExternalNotificationConfig_size + ModuleConfig_MQTTConfig_size + \
ModuleConfig_RangeTestConfig_size + ModuleConfig_SerialConfig_size + ModuleConfig_StoreForwardConfig_size + \
ModuleConfig_TelemetryConfig_size + ModuleConfig_size)
ModuleConfig_TelemetryConfig_size + ModuleConfig_size)

Wyświetl plik

@ -5,6 +5,7 @@
#include "NodeDB.h"
#include "PowerFSM.h"
#include "RadioInterface.h"
#include "TypeConversions.h"
#include "configuration.h"
#include "main.h"
#include "xmodem.h"
@ -40,9 +41,8 @@ void PhoneAPI::handleStartConfig()
state = STATE_SEND_MY_INFO;
LOG_INFO("Starting API client config\n");
nodeInfoForPhone = NULL; // Don't keep returning old nodeinfos
nodeDB.resetReadPointer(); // FIXME, this read pointer should be moved out of nodeDB and into this class - because
// this will break once we have multiple instances of PhoneAPI running independently
nodeInfoForPhone.num = 0; // Don't keep returning old nodeinfos
resetReadIndex();
}
void PhoneAPI::close()
@ -144,25 +144,23 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
LOG_INFO("getFromRadio=STATE_SEND_MY_INFO\n");
// If the user has specified they don't want our node to share its location, make sure to tell the phone
// app not to send locations on our behalf.
myNodeInfo.has_gps = gps && gps->isConnected(); // Update with latest GPS connect info
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_my_info_tag;
fromRadioScratch.my_info = myNodeInfo;
state = STATE_SEND_NODEINFO;
service.refreshMyNodeInfo(); // Update my NodeInfo because the client will be asking for it soon.
service.refreshLocalMeshNode(); // Update my NodeInfo because the client will be asking for it soon.
break;
case STATE_SEND_NODEINFO: {
LOG_INFO("getFromRadio=STATE_SEND_NODEINFO\n");
const meshtastic_NodeInfo *info = nodeInfoForPhone;
nodeInfoForPhone = NULL; // We just consumed a nodeinfo, will need a new one next time
if (info) {
LOG_INFO("Sending nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", info->num, info->last_heard, info->user.id,
info->user.long_name);
if (nodeInfoForPhone.num != 0) {
LOG_INFO("nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", nodeInfoForPhone.num, nodeInfoForPhone.last_heard,
nodeInfoForPhone.user.id, nodeInfoForPhone.user.long_name);
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_node_info_tag;
fromRadioScratch.node_info = *info;
fromRadioScratch.node_info = nodeInfoForPhone;
// Stay in current state until done sending nodeinfos
nodeInfoForPhone.num = 0; // We just consumed a nodeinfo, will need a new one next time
} else {
LOG_INFO("Done sending nodeinfos\n");
state = STATE_SEND_CHANNELS;
@ -372,8 +370,12 @@ bool PhoneAPI::available()
return true;
case STATE_SEND_NODEINFO:
if (!nodeInfoForPhone)
nodeInfoForPhone = nodeDB.readNextInfo();
if (nodeInfoForPhone.num == 0) {
auto nextNode = nodeDB.readNextMeshNode(readIndex);
if (nextNode) {
nodeInfoForPhone = ConvertToNodeInfo(nextNode);
}
}
return true; // Always say we have something, because we might need to advance our state machine
case STATE_SEND_PACKETS: {
@ -428,4 +430,4 @@ int PhoneAPI::onNotify(uint32_t newValue)
}
return 0;
}
}

Wyświetl plik

@ -51,13 +51,16 @@ class PhoneAPI
meshtastic_QueueStatus *queueStatusPacketForPhone = NULL;
/// We temporarily keep the nodeInfo here between the call to available and getFromRadio
const meshtastic_NodeInfo *nodeInfoForPhone = NULL;
meshtastic_NodeInfo nodeInfoForPhone = meshtastic_NodeInfo_init_default;
meshtastic_ToRadio toRadioScratch = {
0}; // this is a static scratch object, any data must be copied elsewhere before returning
/// Use to ensure that clients don't get confused about old messages from the radio
uint32_t config_nonce = 0;
uint32_t readIndex = 0;
void resetReadIndex() { readIndex = 0; }
public:
PhoneAPI();

Wyświetl plik

@ -52,7 +52,7 @@ template <class T> class ProtobufModule : protected SinglePortModule
*/
const char *getSenderShortName(const meshtastic_MeshPacket &mp)
{
auto node = nodeDB.getNode(getFrom(&mp));
auto node = nodeDB.getMeshNode(getFrom(&mp));
const char *sender = (node) ? node->user.short_name : "???";
return sender;
}
@ -86,4 +86,4 @@ template <class T> class ProtobufModule : protected SinglePortModule
return handleReceivedProtobuf(mp, decoded) ? ProcessMessage::STOP : ProcessMessage::CONTINUE;
}
};
};

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -406,4 +406,4 @@ void RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
// bits
enableInterrupt(isrTxLevel0);
}
}
}

Wyświetl plik

@ -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

Wyświetl plik

@ -178,7 +178,7 @@ ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
}
if (!p->channel) { // don't override if a channel was requested
p->channel = nodeDB.getNodeChannel(p->to);
p->channel = nodeDB.getMeshNodeChannel(p->to);
LOG_DEBUG("localSend to channel %d\n", p->channel);
}
@ -493,4 +493,4 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p)
handleReceived(p);
packetPool.release(p);
}
}

Wyświetl plik

@ -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

Wyświetl plik

@ -0,0 +1,31 @@
#pragma once
#include "SX126xInterface.h"
#ifdef ARCH_STM32WL
/**
* Our adapter for STM32WLE5JC radios
*/
class STM32WLE5JCInterface : public SX126xInterface<STM32WLx>
{
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

Wyświetl plik

@ -0,0 +1,54 @@
#include "mesh/generated/meshtastic/deviceonly.pb.h"
#include "mesh/generated/meshtastic/mesh.pb.h"
inline static meshtastic_NodeInfo ConvertToNodeInfo(const meshtastic_NodeInfoLite *lite)
{
meshtastic_NodeInfo info = meshtastic_NodeInfo_init_default;
info.num = lite->num;
info.snr = lite->snr;
info.last_heard = lite->last_heard;
info.channel = lite->channel;
if (lite->has_position) {
info.has_position = true;
info.position.latitude_i = lite->position.latitude_i;
info.position.longitude_i = lite->position.longitude_i;
info.position.altitude = lite->position.altitude;
info.position.location_source = lite->position.location_source;
info.position.time = lite->position.time;
}
if (lite->has_user) {
info.has_user = true;
info.user = lite->user;
}
if (lite->has_device_metrics) {
info.has_device_metrics = true;
info.device_metrics = lite->device_metrics;
}
return info;
}
inline static meshtastic_PositionLite ConvertToPositionLite(meshtastic_Position position)
{
meshtastic_PositionLite lite = meshtastic_PositionLite_init_default;
lite.latitude_i = position.latitude_i;
lite.longitude_i = position.longitude_i;
lite.altitude = position.altitude;
lite.location_source = position.location_source;
lite.time = position.time;
return lite;
}
inline static meshtastic_Position ConvertToPosition(meshtastic_PositionLite lite)
{
meshtastic_Position position = meshtastic_Position_init_default;
position.latitude_i = lite.latitude_i;
position.longitude_i = lite.longitude_i;
position.altitude = lite.altitude;
position.location_source = lite.location_source;
position.time = lite.time;
return position;
}

Wyświetl plik

@ -74,7 +74,7 @@ template <class T> 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

Wyświetl plik

@ -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;

Wyświetl plik

@ -311,6 +311,8 @@ typedef struct _meshtastic_Config_PowerConfig {
While in light sleep when we receive packets on the LoRa radio we will wake and handle them and stay awake in no BLE mode for this value
0 for default of 10 seconds */
uint32_t min_wake_secs;
/* I2C address of INA_2XX to use for reading device battery voltage */
uint8_t device_battery_ina_address;
} meshtastic_Config_PowerConfig;
typedef struct _meshtastic_Config_NetworkConfig_IpV4Config {
@ -534,7 +536,7 @@ extern "C" {
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0}
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""}
#define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0}
@ -543,7 +545,7 @@ extern "C" {
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0}
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""}
#define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0}
@ -579,6 +581,7 @@ extern "C" {
#define meshtastic_Config_PowerConfig_sds_secs_tag 6
#define meshtastic_Config_PowerConfig_ls_secs_tag 7
#define meshtastic_Config_PowerConfig_min_wake_secs_tag 8
#define meshtastic_Config_PowerConfig_device_battery_ina_address_tag 9
#define meshtastic_Config_NetworkConfig_IpV4Config_ip_tag 1
#define meshtastic_Config_NetworkConfig_IpV4Config_gateway_tag 2
#define meshtastic_Config_NetworkConfig_IpV4Config_subnet_tag 3
@ -682,7 +685,8 @@ X(a, STATIC, SINGULAR, UINT32, wait_bluetooth_secs, 4) \
X(a, STATIC, SINGULAR, UINT32, mesh_sds_timeout_secs, 5) \
X(a, STATIC, SINGULAR, UINT32, sds_secs, 6) \
X(a, STATIC, SINGULAR, UINT32, ls_secs, 7) \
X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 8)
X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 8) \
X(a, STATIC, SINGULAR, UINT32, device_battery_ina_address, 9)
#define meshtastic_Config_PowerConfig_CALLBACK NULL
#define meshtastic_Config_PowerConfig_DEFAULT NULL
@ -776,7 +780,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg;
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
#define meshtastic_Config_NetworkConfig_size 195
#define meshtastic_Config_PositionConfig_size 54
#define meshtastic_Config_PowerConfig_size 43
#define meshtastic_Config_PowerConfig_size 46
#define meshtastic_Config_size 198
#ifdef __cplusplus

Wyświetl plik

@ -9,6 +9,12 @@
PB_BIND(meshtastic_DeviceState, meshtastic_DeviceState, 4)
PB_BIND(meshtastic_NodeInfoLite, meshtastic_NodeInfoLite, AUTO)
PB_BIND(meshtastic_PositionLite, meshtastic_PositionLite, AUTO)
PB_BIND(meshtastic_ChannelFile, meshtastic_ChannelFile, 2)

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -72,6 +72,9 @@ typedef struct _meshtastic_LocalModuleConfig {
/* The part of the config that is specific to the Remote Hardware module */
bool has_remote_hardware;
meshtastic_ModuleConfig_RemoteHardwareConfig remote_hardware;
/* The part of the config that is specific to the Neighbor Info module */
bool has_neighbor_info;
meshtastic_ModuleConfig_NeighborInfoConfig neighbor_info;
} meshtastic_LocalModuleConfig;
@ -81,9 +84,9 @@ extern "C" {
/* Initializer values for message structs */
#define meshtastic_LocalConfig_init_default {false, meshtastic_Config_DeviceConfig_init_default, false, meshtastic_Config_PositionConfig_init_default, false, meshtastic_Config_PowerConfig_init_default, false, meshtastic_Config_NetworkConfig_init_default, false, meshtastic_Config_DisplayConfig_init_default, false, meshtastic_Config_LoRaConfig_init_default, false, meshtastic_Config_BluetoothConfig_init_default, 0}
#define meshtastic_LocalModuleConfig_init_default {false, meshtastic_ModuleConfig_MQTTConfig_init_default, false, meshtastic_ModuleConfig_SerialConfig_init_default, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_default, false, meshtastic_ModuleConfig_StoreForwardConfig_init_default, false, meshtastic_ModuleConfig_RangeTestConfig_init_default, false, meshtastic_ModuleConfig_TelemetryConfig_init_default, false, meshtastic_ModuleConfig_CannedMessageConfig_init_default, 0, false, meshtastic_ModuleConfig_AudioConfig_init_default, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_default}
#define meshtastic_LocalModuleConfig_init_default {false, meshtastic_ModuleConfig_MQTTConfig_init_default, false, meshtastic_ModuleConfig_SerialConfig_init_default, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_default, false, meshtastic_ModuleConfig_StoreForwardConfig_init_default, false, meshtastic_ModuleConfig_RangeTestConfig_init_default, false, meshtastic_ModuleConfig_TelemetryConfig_init_default, false, meshtastic_ModuleConfig_CannedMessageConfig_init_default, 0, false, meshtastic_ModuleConfig_AudioConfig_init_default, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_default, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_default}
#define meshtastic_LocalConfig_init_zero {false, meshtastic_Config_DeviceConfig_init_zero, false, meshtastic_Config_PositionConfig_init_zero, false, meshtastic_Config_PowerConfig_init_zero, false, meshtastic_Config_NetworkConfig_init_zero, false, meshtastic_Config_DisplayConfig_init_zero, false, meshtastic_Config_LoRaConfig_init_zero, false, meshtastic_Config_BluetoothConfig_init_zero, 0}
#define meshtastic_LocalModuleConfig_init_zero {false, meshtastic_ModuleConfig_MQTTConfig_init_zero, false, meshtastic_ModuleConfig_SerialConfig_init_zero, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero, false, meshtastic_ModuleConfig_StoreForwardConfig_init_zero, false, meshtastic_ModuleConfig_RangeTestConfig_init_zero, false, meshtastic_ModuleConfig_TelemetryConfig_init_zero, false, meshtastic_ModuleConfig_CannedMessageConfig_init_zero, 0, false, meshtastic_ModuleConfig_AudioConfig_init_zero, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero}
#define meshtastic_LocalModuleConfig_init_zero {false, meshtastic_ModuleConfig_MQTTConfig_init_zero, false, meshtastic_ModuleConfig_SerialConfig_init_zero, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero, false, meshtastic_ModuleConfig_StoreForwardConfig_init_zero, false, meshtastic_ModuleConfig_RangeTestConfig_init_zero, false, meshtastic_ModuleConfig_TelemetryConfig_init_zero, false, meshtastic_ModuleConfig_CannedMessageConfig_init_zero, 0, false, meshtastic_ModuleConfig_AudioConfig_init_zero, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_zero}
/* Field tags (for use in manual encoding/decoding) */
#define meshtastic_LocalConfig_device_tag 1
@ -104,6 +107,7 @@ extern "C" {
#define meshtastic_LocalModuleConfig_version_tag 8
#define meshtastic_LocalModuleConfig_audio_tag 9
#define meshtastic_LocalModuleConfig_remote_hardware_tag 10
#define meshtastic_LocalModuleConfig_neighbor_info_tag 11
/* Struct field encoding specification for nanopb */
#define meshtastic_LocalConfig_FIELDLIST(X, a) \
@ -135,7 +139,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, telemetry, 6) \
X(a, STATIC, OPTIONAL, MESSAGE, canned_message, 7) \
X(a, STATIC, SINGULAR, UINT32, version, 8) \
X(a, STATIC, OPTIONAL, MESSAGE, audio, 9) \
X(a, STATIC, OPTIONAL, MESSAGE, remote_hardware, 10)
X(a, STATIC, OPTIONAL, MESSAGE, remote_hardware, 10) \
X(a, STATIC, OPTIONAL, MESSAGE, neighbor_info, 11)
#define meshtastic_LocalModuleConfig_CALLBACK NULL
#define meshtastic_LocalModuleConfig_DEFAULT NULL
#define meshtastic_LocalModuleConfig_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
@ -147,6 +152,7 @@ X(a, STATIC, OPTIONAL, MESSAGE, remote_hardware, 10)
#define meshtastic_LocalModuleConfig_canned_message_MSGTYPE meshtastic_ModuleConfig_CannedMessageConfig
#define meshtastic_LocalModuleConfig_audio_MSGTYPE meshtastic_ModuleConfig_AudioConfig
#define meshtastic_LocalModuleConfig_remote_hardware_MSGTYPE meshtastic_ModuleConfig_RemoteHardwareConfig
#define meshtastic_LocalModuleConfig_neighbor_info_MSGTYPE meshtastic_ModuleConfig_NeighborInfoConfig
extern const pb_msgdesc_t meshtastic_LocalConfig_msg;
extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
@ -156,8 +162,8 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
#define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg
/* Maximum encoded size of messages (where known) */
#define meshtastic_LocalConfig_size 458
#define meshtastic_LocalModuleConfig_size 533
#define meshtastic_LocalConfig_size 461
#define meshtastic_LocalModuleConfig_size 545
#ifdef __cplusplus
} /* extern "C" */

Wyświetl plik

@ -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;

Wyświetl plik

@ -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)

Wyświetl plik

@ -58,7 +58,9 @@ typedef enum _meshtastic_ModuleConfig_SerialConfig_Serial_Mode {
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_SIMPLE = 1,
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_PROTO = 2,
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG = 3,
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA = 4
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA = 4,
/* NMEA messages specifically tailored for CalTopo */
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO = 5
} meshtastic_ModuleConfig_SerialConfig_Serial_Mode;
/* TODO: REPLACE */
@ -112,6 +114,15 @@ typedef struct _meshtastic_ModuleConfig_MQTTConfig {
char root[16];
} meshtastic_ModuleConfig_MQTTConfig;
/* NeighborInfoModule Config */
typedef struct _meshtastic_ModuleConfig_NeighborInfoConfig {
/* Whether the Module is enabled */
bool enabled;
/* Interval in seconds of how often we should try to send our
Neighbor Info to the mesh */
uint32_t update_interval;
} meshtastic_ModuleConfig_NeighborInfoConfig;
/* Audio Config for codec2 voice */
typedef struct _meshtastic_ModuleConfig_AudioConfig {
/* Whether Audio is enabled */
@ -132,21 +143,24 @@ typedef struct _meshtastic_ModuleConfig_AudioConfig {
/* Serial Config */
typedef struct _meshtastic_ModuleConfig_SerialConfig {
/* Preferences for the SerialModule
FIXME - Move this out of UserPreferences and into a section for module configuration. */
/* Preferences for the SerialModule */
bool enabled;
/* TODO: REPLACE */
bool echo;
/* TODO: REPLACE */
/* RX pin (should match Arduino gpio pin number) */
uint32_t rxd;
/* TODO: REPLACE */
/* TX pin (should match Arduino gpio pin number) */
uint32_t txd;
/* TODO: REPLACE */
/* Serial baud rate */
meshtastic_ModuleConfig_SerialConfig_Serial_Baud baud;
/* TODO: REPLACE */
uint32_t timeout;
/* TODO: REPLACE */
/* Mode for serial module operation */
meshtastic_ModuleConfig_SerialConfig_Serial_Mode mode;
/* Overrides the platform's defacto Serial port instance to use with Serial module config settings
This is currently only usable in output modes like NMEA / CalTopo and may behave strangely or not work at all in other modes
Existing logging over the Serial Console will still be present */
bool override_console_serial_port;
} meshtastic_ModuleConfig_SerialConfig;
/* External Notifications Config */
@ -308,6 +322,8 @@ typedef struct _meshtastic_ModuleConfig {
meshtastic_ModuleConfig_AudioConfig audio;
/* TODO: REPLACE */
meshtastic_ModuleConfig_RemoteHardwareConfig remote_hardware;
/* TODO: REPLACE */
meshtastic_ModuleConfig_NeighborInfoConfig neighbor_info;
} payload_variant;
} meshtastic_ModuleConfig;
@ -330,8 +346,8 @@ extern "C" {
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Baud)(meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600+1))
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN meshtastic_ModuleConfig_SerialConfig_Serial_Mode_DEFAULT
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MAX meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Mode)(meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA+1))
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MAX meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Mode)(meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO+1))
#define _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE
#define _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MAX meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK
@ -340,6 +356,7 @@ extern "C" {
#define meshtastic_ModuleConfig_AudioConfig_bitrate_ENUMTYPE meshtastic_ModuleConfig_AudioConfig_Audio_Baud
#define meshtastic_ModuleConfig_SerialConfig_baud_ENUMTYPE meshtastic_ModuleConfig_SerialConfig_Serial_Baud
@ -360,8 +377,9 @@ extern "C" {
#define meshtastic_ModuleConfig_init_default {0, {meshtastic_ModuleConfig_MQTTConfig_init_default}}
#define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, ""}
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_default {0, 0, 0, {meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default}}
#define meshtastic_ModuleConfig_NeighborInfoConfig_init_default {0, 0}
#define meshtastic_ModuleConfig_AudioConfig_init_default {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN}
#define meshtastic_ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0}
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0}
@ -371,8 +389,9 @@ extern "C" {
#define meshtastic_ModuleConfig_init_zero {0, {meshtastic_ModuleConfig_MQTTConfig_init_zero}}
#define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, ""}
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero {0, 0, 0, {meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero}}
#define meshtastic_ModuleConfig_NeighborInfoConfig_init_zero {0, 0}
#define meshtastic_ModuleConfig_AudioConfig_init_zero {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN}
#define meshtastic_ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0}
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0}
@ -389,6 +408,8 @@ extern "C" {
#define meshtastic_ModuleConfig_MQTTConfig_json_enabled_tag 6
#define meshtastic_ModuleConfig_MQTTConfig_tls_enabled_tag 7
#define meshtastic_ModuleConfig_MQTTConfig_root_tag 8
#define meshtastic_ModuleConfig_NeighborInfoConfig_enabled_tag 1
#define meshtastic_ModuleConfig_NeighborInfoConfig_update_interval_tag 2
#define meshtastic_ModuleConfig_AudioConfig_codec2_enabled_tag 1
#define meshtastic_ModuleConfig_AudioConfig_ptt_pin_tag 2
#define meshtastic_ModuleConfig_AudioConfig_bitrate_tag 3
@ -403,6 +424,7 @@ extern "C" {
#define meshtastic_ModuleConfig_SerialConfig_baud_tag 5
#define meshtastic_ModuleConfig_SerialConfig_timeout_tag 6
#define meshtastic_ModuleConfig_SerialConfig_mode_tag 7
#define meshtastic_ModuleConfig_SerialConfig_override_console_serial_port_tag 8
#define meshtastic_ModuleConfig_ExternalNotificationConfig_enabled_tag 1
#define meshtastic_ModuleConfig_ExternalNotificationConfig_output_ms_tag 2
#define meshtastic_ModuleConfig_ExternalNotificationConfig_output_tag 3
@ -458,6 +480,7 @@ extern "C" {
#define meshtastic_ModuleConfig_canned_message_tag 7
#define meshtastic_ModuleConfig_audio_tag 8
#define meshtastic_ModuleConfig_remote_hardware_tag 9
#define meshtastic_ModuleConfig_neighbor_info_tag 10
/* Struct field encoding specification for nanopb */
#define meshtastic_ModuleConfig_FIELDLIST(X, a) \
@ -469,7 +492,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,range_test,payload_variant.r
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,telemetry,payload_variant.telemetry), 6) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,canned_message,payload_variant.canned_message), 7) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,audio,payload_variant.audio), 8) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,remote_hardware,payload_variant.remote_hardware), 9)
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,remote_hardware,payload_variant.remote_hardware), 9) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,neighbor_info,payload_variant.neighbor_info), 10)
#define meshtastic_ModuleConfig_CALLBACK NULL
#define meshtastic_ModuleConfig_DEFAULT NULL
#define meshtastic_ModuleConfig_payload_variant_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
@ -481,6 +505,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,remote_hardware,payload_vari
#define meshtastic_ModuleConfig_payload_variant_canned_message_MSGTYPE meshtastic_ModuleConfig_CannedMessageConfig
#define meshtastic_ModuleConfig_payload_variant_audio_MSGTYPE meshtastic_ModuleConfig_AudioConfig
#define meshtastic_ModuleConfig_payload_variant_remote_hardware_MSGTYPE meshtastic_ModuleConfig_RemoteHardwareConfig
#define meshtastic_ModuleConfig_payload_variant_neighbor_info_MSGTYPE meshtastic_ModuleConfig_NeighborInfoConfig
#define meshtastic_ModuleConfig_MQTTConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
@ -502,6 +527,12 @@ X(a, STATIC, REPEATED, MESSAGE, available_pins, 3)
#define meshtastic_ModuleConfig_RemoteHardwareConfig_DEFAULT NULL
#define meshtastic_ModuleConfig_RemoteHardwareConfig_available_pins_MSGTYPE meshtastic_RemoteHardwarePin
#define meshtastic_ModuleConfig_NeighborInfoConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
X(a, STATIC, SINGULAR, UINT32, update_interval, 2)
#define meshtastic_ModuleConfig_NeighborInfoConfig_CALLBACK NULL
#define meshtastic_ModuleConfig_NeighborInfoConfig_DEFAULT NULL
#define meshtastic_ModuleConfig_AudioConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, BOOL, codec2_enabled, 1) \
X(a, STATIC, SINGULAR, UINT32, ptt_pin, 2) \
@ -520,7 +551,8 @@ X(a, STATIC, SINGULAR, UINT32, rxd, 3) \
X(a, STATIC, SINGULAR, UINT32, txd, 4) \
X(a, STATIC, SINGULAR, UENUM, baud, 5) \
X(a, STATIC, SINGULAR, UINT32, timeout, 6) \
X(a, STATIC, SINGULAR, UENUM, mode, 7)
X(a, STATIC, SINGULAR, UENUM, mode, 7) \
X(a, STATIC, SINGULAR, BOOL, override_console_serial_port, 8)
#define meshtastic_ModuleConfig_SerialConfig_CALLBACK NULL
#define meshtastic_ModuleConfig_SerialConfig_DEFAULT NULL
@ -594,6 +626,7 @@ X(a, STATIC, SINGULAR, UENUM, type, 3)
extern const pb_msgdesc_t meshtastic_ModuleConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_MQTTConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_RemoteHardwareConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_NeighborInfoConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_AudioConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_SerialConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_ExternalNotificationConfig_msg;
@ -607,6 +640,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
#define meshtastic_ModuleConfig_fields &meshtastic_ModuleConfig_msg
#define meshtastic_ModuleConfig_MQTTConfig_fields &meshtastic_ModuleConfig_MQTTConfig_msg
#define meshtastic_ModuleConfig_RemoteHardwareConfig_fields &meshtastic_ModuleConfig_RemoteHardwareConfig_msg
#define meshtastic_ModuleConfig_NeighborInfoConfig_fields &meshtastic_ModuleConfig_NeighborInfoConfig_msg
#define meshtastic_ModuleConfig_AudioConfig_fields &meshtastic_ModuleConfig_AudioConfig_msg
#define meshtastic_ModuleConfig_SerialConfig_fields &meshtastic_ModuleConfig_SerialConfig_msg
#define meshtastic_ModuleConfig_ExternalNotificationConfig_fields &meshtastic_ModuleConfig_ExternalNotificationConfig_msg
@ -621,9 +655,10 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
#define meshtastic_ModuleConfig_CannedMessageConfig_size 49
#define meshtastic_ModuleConfig_ExternalNotificationConfig_size 40
#define meshtastic_ModuleConfig_MQTTConfig_size 220
#define meshtastic_ModuleConfig_NeighborInfoConfig_size 8
#define meshtastic_ModuleConfig_RangeTestConfig_size 10
#define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96
#define meshtastic_ModuleConfig_SerialConfig_size 26
#define meshtastic_ModuleConfig_SerialConfig_size 28
#define meshtastic_ModuleConfig_StoreForwardConfig_size 22
#define meshtastic_ModuleConfig_TelemetryConfig_size 26
#define meshtastic_ModuleConfig_size 223

Wyświetl plik

@ -521,11 +521,23 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
void AdminModule::handleGetNodeRemoteHardwarePins(const meshtastic_MeshPacket &req)
{
// We create the reply here
meshtastic_AdminMessage r = meshtastic_AdminMessage_init_default;
memcpy(r.get_node_remote_hardware_pins_response.node_remote_hardware_pins, devicestate.node_remote_hardware_pins,
sizeof(devicestate.node_remote_hardware_pins));
r.which_payload_variant = meshtastic_AdminMessage_get_node_remote_hardware_pins_response_tag;
for (uint8_t i = 0; i < devicestate.node_remote_hardware_pins_count; i++) {
if (devicestate.node_remote_hardware_pins[i].node_num == 0 || !devicestate.node_remote_hardware_pins[i].has_pin) {
continue;
}
r.get_node_remote_hardware_pins_response.node_remote_hardware_pins[i] = devicestate.node_remote_hardware_pins[i];
}
for (uint8_t i = 0; i < moduleConfig.remote_hardware.available_pins_count; i++) {
if (!moduleConfig.remote_hardware.available_pins[i].gpio_pin) {
continue;
}
meshtastic_NodeRemoteHardwarePin nodePin = meshtastic_NodeRemoteHardwarePin_init_default;
nodePin.node_num = nodeDB.getNodeNum();
nodePin.pin = moduleConfig.remote_hardware.available_pins[i];
r.get_node_remote_hardware_pins_response.node_remote_hardware_pins[i + 12] = nodePin;
}
myReply = allocDataProtobuf(r);
}
@ -541,9 +553,8 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
{
meshtastic_AdminMessage r = meshtastic_AdminMessage_init_default;
meshtastic_DeviceConnectionStatus conn;
meshtastic_DeviceConnectionStatus conn = meshtastic_DeviceConnectionStatus_init_zero;
conn.wifi = {0};
#if HAS_WIFI
conn.has_wifi = true;
conn.wifi.has_status = true;
@ -559,11 +570,8 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
conn.wifi.status.is_mqtt_connected = mqtt && mqtt->connected();
conn.wifi.status.is_syslog_connected = false; // FIXME wire this up
}
#else
conn.has_wifi = false;
#endif
conn.ethernet = {0};
#if HAS_ETHERNET
conn.has_ethernet = true;
conn.ethernet.has_status = true;
@ -575,8 +583,6 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
} else {
conn.ethernet.status.is_connected = false;
}
#else
conn.has_ethernet = false;
#endif
#if HAS_BLUETOOTH

Wyświetl plik

@ -305,13 +305,14 @@ int32_t CannedMessageModule::runOnce()
switch (this->payload) {
case 0xb4: // left
if (this->destSelect) {
size_t numNodes = nodeDB.getNumNodes();
size_t numMeshNodes = nodeDB.getNumMeshNodes();
if (this->dest == NODENUM_BROADCAST) {
this->dest = nodeDB.getNodeNum();
}
for (unsigned int i = 0; i < numNodes; i++) {
if (nodeDB.getNodeByIndex(i)->num == this->dest) {
this->dest = (i > 0) ? nodeDB.getNodeByIndex(i - 1)->num : nodeDB.getNodeByIndex(numNodes - 1)->num;
for (unsigned int i = 0; i < numMeshNodes; i++) {
if (nodeDB.getMeshNodeByIndex(i)->num == this->dest) {
this->dest =
(i > 0) ? nodeDB.getMeshNodeByIndex(i - 1)->num : nodeDB.getMeshNodeByIndex(numMeshNodes - 1)->num;
break;
}
}
@ -326,13 +327,14 @@ int32_t CannedMessageModule::runOnce()
break;
case 0xb7: // right
if (this->destSelect) {
size_t numNodes = nodeDB.getNumNodes();
size_t numMeshNodes = nodeDB.getNumMeshNodes();
if (this->dest == NODENUM_BROADCAST) {
this->dest = nodeDB.getNodeNum();
}
for (unsigned int i = 0; i < numNodes; i++) {
if (nodeDB.getNodeByIndex(i)->num == this->dest) {
this->dest = (i < numNodes - 1) ? nodeDB.getNodeByIndex(i + 1)->num : nodeDB.getNodeByIndex(0)->num;
for (unsigned int i = 0; i < numMeshNodes; i++) {
if (nodeDB.getMeshNodeByIndex(i)->num == this->dest) {
this->dest =
(i < numMeshNodes - 1) ? nodeDB.getMeshNodeByIndex(i + 1)->num : nodeDB.getMeshNodeByIndex(0)->num;
break;
}
}
@ -409,7 +411,7 @@ const char *CannedMessageModule::getNodeName(NodeNum node)
if (node == NODENUM_BROADCAST) {
return "Broadcast";
} else {
meshtastic_NodeInfo *info = nodeDB.getNode(node);
meshtastic_NodeInfoLite *info = nodeDB.getMeshNode(node);
if (info != NULL) {
return info->user.long_name;
} else {

Wyświetl plik

@ -11,7 +11,7 @@
#include "main.h"
#ifdef RAK4630
#include <NCP5623.h>
#include <graphics/RAKled.h>
NCP5623 rgb;
uint8_t red = 0;

Wyświetl plik

@ -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 <NonBlockingRtttl.h>
#else
// Noop class for portduino.

Wyświetl plik

@ -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();

Wyświetl plik

@ -3,6 +3,7 @@
#include "NodeDB.h"
#include "RTC.h"
#include "Router.h"
#include "TypeConversions.h"
#include "airtime.h"
#include "configuration.h"
#include "gps/GeoCoord.h"
@ -56,55 +57,57 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
meshtastic_MeshPacket *PositionModule::allocReply()
{
meshtastic_NodeInfo *node = service.refreshMyNodeInfo(); // should guarantee there is now a position
meshtastic_NodeInfoLite *node = service.refreshLocalMeshNode(); // should guarantee there is now a position
assert(node->has_position);
node->position.seq_number++;
// configuration of POSITION packet
// consider making this a function argument?
uint32_t pos_flags = config.position.position_flags;
// Populate a Position struct with ONLY the requested fields
meshtastic_Position p = meshtastic_Position_init_default; // Start with an empty structure
if (localPosition.latitude_i == 0 && localPosition.longitude_i == 0) {
localPosition = ConvertToPosition(node->position);
}
localPosition.seq_number++;
// lat/lon are unconditionally included - IF AVAILABLE!
p.latitude_i = node->position.latitude_i;
p.longitude_i = node->position.longitude_i;
p.time = node->position.time;
p.latitude_i = localPosition.latitude_i;
p.longitude_i = localPosition.longitude_i;
p.time = localPosition.time;
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE) {
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE_MSL)
p.altitude = node->position.altitude;
p.altitude = localPosition.altitude;
else
p.altitude_hae = node->position.altitude_hae;
p.altitude_hae = localPosition.altitude_hae;
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_GEOIDAL_SEPARATION)
p.altitude_geoidal_separation = node->position.altitude_geoidal_separation;
p.altitude_geoidal_separation = localPosition.altitude_geoidal_separation;
}
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_DOP) {
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_HVDOP) {
p.HDOP = node->position.HDOP;
p.VDOP = node->position.VDOP;
p.HDOP = localPosition.HDOP;
p.VDOP = localPosition.VDOP;
} else
p.PDOP = node->position.PDOP;
p.PDOP = localPosition.PDOP;
}
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_SATINVIEW)
p.sats_in_view = node->position.sats_in_view;
p.sats_in_view = localPosition.sats_in_view;
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_TIMESTAMP)
p.timestamp = node->position.timestamp;
p.timestamp = localPosition.timestamp;
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_SEQ_NO)
p.seq_number = node->position.seq_number;
p.seq_number = localPosition.seq_number;
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_HEADING)
p.ground_track = node->position.ground_track;
p.ground_track = localPosition.ground_track;
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_SPEED)
p.ground_speed = node->position.ground_speed;
p.ground_speed = localPosition.ground_speed;
// Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other
// nodes shouldn't trust it anyways) Note: we allow a device with a local GPS to include the time, so that gpsless
@ -144,7 +147,7 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha
int32_t PositionModule::runOnce()
{
meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
// We limit our GPS broadcasts to a max rate
uint32_t now = millis();
@ -154,7 +157,7 @@ int32_t PositionModule::runOnce()
if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) {
// Only send packets if the channel is less than 40% utilized.
if (airTime->isTxAllowedChannelUtil()) {
if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) {
if (hasValidPosition(node)) {
lastGpsSend = now;
lastGpsLatitude = node->position.latitude_i;
@ -164,16 +167,16 @@ int32_t PositionModule::runOnce()
bool requestReplies = currentGeneration != radioGeneration;
currentGeneration = radioGeneration;
LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", node->position.timestamp, requestReplies);
LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", localPosition.timestamp, requestReplies);
sendOurPosition(NODENUM_BROADCAST, requestReplies);
}
}
} else if (config.position.position_broadcast_smart_enabled) {
// Only send packets if the channel is less than 25% utilized or we're a tracker.
if (airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER)) {
meshtastic_NodeInfo *node2 = service.refreshMyNodeInfo(); // should guarantee there is now a position
meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position
if (node2->has_position && (node2->position.latitude_i != 0 || node2->position.longitude_i != 0)) {
if (hasValidPosition(node2)) {
// The minimum distance to travel before we are able to send a new position packet.
const uint32_t distanceTravelThreshold =
config.position.broadcast_smart_minimum_distance > 0 ? config.position.broadcast_smart_minimum_distance : 100;
@ -193,7 +196,7 @@ int32_t PositionModule::runOnce()
LOG_INFO("Sending smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, "
"minTimeInterval=%ims)\n",
node2->position.timestamp, abs(distanceTraveledSinceLastSend), distanceTravelThreshold,
localPosition.timestamp, abs(distanceTraveledSinceLastSend), distanceTravelThreshold,
msSinceLastSend, minimumTimeThreshold);
sendOurPosition(NODENUM_BROADCAST, requestReplies);
@ -211,4 +214,4 @@ int32_t PositionModule::runOnce()
}
return 5000; // to save power only wake for our callback occasionally
}
}

Wyświetl plik

@ -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 <Arduino.h>
#include <FSCommon.h>
/*
As a sender, I can send packets every n seconds. These packets include an incremented PacketID.
@ -28,7 +28,7 @@ uint32_t packetSequence = 0;
int32_t RangeTestModule::runOnce()
{
#ifdef ARCH_ESP32
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
/*
Uncomment the preferences below if you want to use the module
@ -60,7 +60,6 @@ int32_t RangeTestModule::runOnce()
return disable();
// This thread does not need to run as a receiver
}
} else {
if (moduleConfig.range_test.sender) {
@ -122,7 +121,7 @@ void RangeTestModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket &mp)
{
#ifdef ARCH_ESP32
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
if (moduleConfig.range_test.enabled) {
@ -139,7 +138,7 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket
}
/*
NodeInfo *n = nodeDB.getNode(getFrom(&mp));
NodeInfoLite *n = nodeDB.getMeshNode(getFrom(&mp));
LOG_DEBUG("-----------------------------------------\n");
LOG_DEBUG("p.payload.bytes \"%s\"\n", p.payload.bytes);
@ -153,7 +152,6 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket
LOG_DEBUG("---- Node Information of Received Packet (mp.from):\n");
LOG_DEBUG("n->user.long_name %s\n", n->user.long_name);
LOG_DEBUG("n->user.short_name %s\n", n->user.short_name);
LOG_DEBUG("n->user.macaddr %X\n", n->user.macaddr);
LOG_DEBUG("n->has_position %d\n", n->has_position);
LOG_DEBUG("n->position.latitude_i %d\n", n->position.latitude_i);
LOG_DEBUG("n->position.longitude_i %d\n", n->position.longitude_i);
@ -165,7 +163,6 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket
LOG_DEBUG("-----------------------------------------\n");
*/
}
} else {
LOG_INFO("Range Test Module Disabled\n");
}
@ -177,9 +174,10 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket
bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp)
{
#ifdef ARCH_ESP32
auto &p = mp.decoded;
meshtastic_NodeInfo *n = nodeDB.getNode(getFrom(&mp));
meshtastic_NodeInfoLite *n = nodeDB.getMeshNode(getFrom(&mp));
/*
LOG_DEBUG("-----------------------------------------\n");
LOG_DEBUG("p.payload.bytes \"%s\"\n", p.payload.bytes);
@ -193,7 +191,6 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp)
LOG_DEBUG("---- Node Information of Received Packet (mp.from):\n");
LOG_DEBUG("n->user.long_name %s\n", n->user.long_name);
LOG_DEBUG("n->user.short_name %s\n", n->user.short_name);
LOG_DEBUG("n->user.macaddr %X\n", n->user.macaddr);
LOG_DEBUG("n->has_position %d\n", n->has_position);
LOG_DEBUG("n->position.latitude_i %d\n", n->position.latitude_i);
LOG_DEBUG("n->position.longitude_i %d\n", n->position.longitude_i);
@ -284,6 +281,7 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp)
fileToAppend.printf("\"%s\"\n", p.payload.bytes);
fileToAppend.flush();
fileToAppend.close();
#endif
return 1;
}
}

Wyświetl plik

@ -39,13 +39,12 @@
KNOWN PROBLEMS
* Until the module is initilized by the startup sequence, the TX pin is in a floating
state. Device connected to that pin may see this as "noise".
* Will not work on T-Echo and the Linux device targets.
* Will not work on Linux device targets.
*/
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \
!defined(CONFIG_IDF_TARGET_ESP32C3)
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
#define RX_BUFFER 128
#define TIMEOUT 250
@ -58,19 +57,25 @@
SerialModule *serialModule;
SerialModuleRadio *serialModuleRadio;
#ifdef TTGO_T_ECHO
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("SerialModule") {}
static Print *serialPrint = &Serial;
#else
SerialModule::SerialModule() : StreamAPI(&Serial2), concurrency::OSThread("SerialModule") {}
static Print *serialPrint = &Serial2;
#endif
char serialBytes[meshtastic_Constants_DATA_PAYLOAD_LEN];
size_t serialPayloadSize;
SerialModuleRadio::SerialModuleRadio() : MeshModule("SerialModuleRadio")
{
switch (moduleConfig.serial.mode) {
case meshtastic_ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG:
ourPortNum = meshtastic_PortNum_TEXT_MESSAGE_APP;
break;
case meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA:
case meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO:
ourPortNum = meshtastic_PortNum_POSITION_APP;
break;
default:
@ -95,89 +100,52 @@ int32_t SerialModule::runOnce()
without having to configure it from the PythonAPI or WebUI.
*/
// moduleConfig.serial.enabled = 1;
// moduleConfig.serial.enabled = true;
// moduleConfig.serial.rxd = 35;
// moduleConfig.serial.txd = 15;
// moduleConfig.serial.override_console_serial_port = true;
// moduleConfig.serial.mode = meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO;
// moduleConfig.serial.timeout = 1000;
// moduleConfig.serial.echo = 1;
if (moduleConfig.serial.enabled && moduleConfig.serial.rxd && moduleConfig.serial.txd) {
if (!moduleConfig.serial.enabled)
return disable();
if (moduleConfig.serial.override_console_serial_port || (moduleConfig.serial.rxd && moduleConfig.serial.txd)) {
if (firstTime) {
// Interface with the serial peripheral from in here.
LOG_INFO("Initializing serial peripheral interface\n");
uint32_t baud = 0;
uint32_t baud = getBaudRate();
if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_DEFAULT) {
baud = 38400;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_110) {
baud = 110;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_300) {
baud = 300;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_600) {
baud = 600;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_1200) {
baud = 1200;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_2400) {
baud = 2400;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_4800) {
baud = 4800;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_9600) {
baud = 9600;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_19200) {
baud = 19200;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_38400) {
baud = 38400;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_57600) {
baud = 57600;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_115200) {
baud = 115200;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_230400) {
baud = 230400;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_460800) {
baud = 460800;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_576000) {
baud = 576000;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600) {
baud = 921600;
if (moduleConfig.serial.override_console_serial_port) {
Serial.flush();
serialPrint = &Serial;
// Give it a chance to flush out 💩
delay(10);
}
#ifdef ARCH_ESP32
Serial2.setRxBufferSize(RX_BUFFER);
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
Serial2.setRxBufferSize(RX_BUFFER);
Serial2.begin(baud, SERIAL_8N1, moduleConfig.serial.rxd, moduleConfig.serial.txd);
} else {
Serial.begin(baud);
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
}
#elif !defined(TTGO_T_ECHO)
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
Serial2.setPins(moduleConfig.serial.rxd, moduleConfig.serial.txd);
Serial2.begin(baud, SERIAL_8N1);
Serial2.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
} else {
Serial.begin(baud, SERIAL_8N1);
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
}
#else
if (moduleConfig.serial.rxd && moduleConfig.serial.txd)
Serial2.setPins(moduleConfig.serial.rxd, moduleConfig.serial.txd);
Serial2.begin(baud, SERIAL_8N1);
Serial.begin(baud, SERIAL_8N1);
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
#endif
if (moduleConfig.serial.timeout) {
Serial2.setTimeout(moduleConfig.serial.timeout); // Number of MS to wait to set the timeout for the string.
} else {
Serial2.setTimeout(TIMEOUT); // Number of MS to wait to set the timeout for the string.
}
serialModuleRadio = new SerialModuleRadio();
firstTime = 0;
@ -186,26 +154,37 @@ int32_t SerialModule::runOnce()
if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_PROTO) {
emitRebooted();
}
} else {
if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_PROTO) {
return runOncePart();
} else if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA) {
// in NMEA mode send out GGA every 2 seconds, Don't read from Port
if (millis() - lastNmeaTime > 2000) {
lastNmeaTime = millis();
printGGA(outbuf, sizeof(outbuf), nodeDB.getNode(myNodeInfo.my_node_num)->position);
Serial2.printf("%s", outbuf);
printGGA(outbuf, sizeof(outbuf), localPosition);
serialPrint->printf("%s", outbuf);
}
} else {
} else if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO) {
if (millis() - lastNmeaTime > 10000) {
lastNmeaTime = millis();
uint32_t readIndex = 0;
const meshtastic_NodeInfoLite *tempNodeInfo = nodeDB.readNextMeshNode(readIndex);
while (tempNodeInfo != NULL && tempNodeInfo->has_user && hasValidPosition(tempNodeInfo)) {
printWPL(outbuf, sizeof(outbuf), tempNodeInfo->position, tempNodeInfo->user.long_name, true);
serialPrint->printf("%s", outbuf);
tempNodeInfo = nodeDB.readNextMeshNode(readIndex);
}
}
}
#ifndef TTGO_T_ECHO
else {
while (Serial2.available()) {
serialPayloadSize = Serial2.readBytes(serialBytes, meshtastic_Constants_DATA_PAYLOAD_LEN);
serialModuleRadio->sendPayload();
}
}
#endif
}
return (10);
} else {
return disable();
@ -262,23 +241,23 @@ ProcessMessage SerialModuleRadio::handleReceived(const meshtastic_MeshPacket &mp
if (lastRxID != mp.id) {
lastRxID = mp.id;
// LOG_DEBUG("* * Message came this device\n");
// Serial2.println("* * Message came this device");
Serial2.printf("%s", p.payload.bytes);
// serialPrint->println("* * Message came this device");
serialPrint->printf("%s", p.payload.bytes);
}
}
} else {
if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_DEFAULT ||
moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_SIMPLE) {
Serial2.printf("%s", p.payload.bytes);
serialPrint->printf("%s", p.payload.bytes);
} else if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG) {
meshtastic_NodeInfo *node = nodeDB.getNode(getFrom(&mp));
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp));
String sender = (node && node->has_user) ? node->user.short_name : "???";
Serial2.println();
Serial2.printf("%s: %s", sender, p.payload.bytes);
Serial2.println();
} else if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA) {
serialPrint->println();
serialPrint->printf("%s: %s", sender, p.payload.bytes);
serialPrint->println();
} else if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA ||
moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO) {
// Decode the Payload some more
meshtastic_Position scratch;
meshtastic_Position *decoded = NULL;
@ -288,12 +267,49 @@ ProcessMessage SerialModuleRadio::handleReceived(const meshtastic_MeshPacket &mp
decoded = &scratch;
}
// send position packet as WPL to the serial port
printWPL(outbuf, sizeof(outbuf), *decoded, nodeDB.getNode(getFrom(&mp))->user.long_name);
Serial2.printf("%s", outbuf);
printWPL(outbuf, sizeof(outbuf), *decoded, nodeDB.getMeshNode(getFrom(&mp))->user.long_name,
moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO);
serialPrint->printf("%s", outbuf);
}
}
}
}
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
}
#endif
uint32_t SerialModule::getBaudRate()
{
if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_110) {
return 110;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_300) {
return 300;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_600) {
return 600;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_1200) {
return 1200;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_2400) {
return 2400;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_4800) {
return 4800;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_9600) {
return 9600;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_19200) {
return 19200;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_38400) {
return 38400;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_57600) {
return 57600;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_115200) {
return 115200;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_230400) {
return 230400;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_460800) {
return 460800;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_576000) {
return 576000;
} else if (moduleConfig.serial.baud == meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600) {
return 921600;
}
return BAUD;
}
#endif

Wyświetl plik

@ -8,8 +8,7 @@
#include <Arduino.h>
#include <functional>
#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;

Wyświetl plik

@ -50,14 +50,14 @@ bool DeviceTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
t.time = getTime();
t.which_variant = meshtastic_Telemetry_device_metrics_tag;
t.variant.device_metrics.air_util_tx = myNodeInfo.air_util_tx;
t.variant.device_metrics.air_util_tx = airTime->utilizationTXPercent();
if (powerStatus->getIsCharging()) {
t.variant.device_metrics.battery_level = MAGIC_USB_BATTERY_LEVEL;
} else {
t.variant.device_metrics.battery_level = powerStatus->getBatteryChargePercent();
}
t.variant.device_metrics.channel_utilization = myNodeInfo.channel_utilization;
t.variant.device_metrics.channel_utilization = airTime->channelUtilizationPercent();
t.variant.device_metrics.voltage = powerStatus->getBatteryVoltageMv() / 1000.0;
LOG_INFO("(Sending): air_util_tx=%f, channel_utilization=%f, battery_level=%i, voltage=%f\n",
@ -78,4 +78,4 @@ bool DeviceTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
service.sendToMesh(p, RX_SRC_LOCAL, true);
}
return true;
}
}

Wyświetl plik

@ -7,6 +7,7 @@
#include "Router.h"
#include "configuration.h"
#include "main.h"
#include "power.h"
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
@ -14,8 +15,6 @@
#include "Sensor/BME280Sensor.h"
#include "Sensor/BME680Sensor.h"
#include "Sensor/BMP280Sensor.h"
#include "Sensor/INA219Sensor.h"
#include "Sensor/INA260Sensor.h"
#include "Sensor/LPS22HBSensor.h"
#include "Sensor/MCP9808Sensor.h"
#include "Sensor/SHT31Sensor.h"
@ -25,8 +24,6 @@ BMP280Sensor bmp280Sensor;
BME280Sensor bme280Sensor;
BME680Sensor bme680Sensor;
MCP9808Sensor mcp9808Sensor;
INA260Sensor ina260Sensor;
INA219Sensor ina219Sensor;
SHTC3Sensor shtc3Sensor;
LPS22HBSensor lps22hbSensor;
SHT31Sensor sht31Sensor;
@ -52,7 +49,7 @@ SHT31Sensor sht31Sensor;
int32_t EnvironmentTelemetryModule::runOnce()
{
int32_t result = INT32_MAX;
uint32_t result = UINT32_MAX;
/*
Uncomment the preferences below if you want to use the module
without having to configure it from the PythonAPI or WebUI.
@ -83,23 +80,22 @@ int32_t EnvironmentTelemetryModule::runOnce()
result = bme680Sensor.runOnce();
if (mcp9808Sensor.hasSensor())
result = mcp9808Sensor.runOnce();
if (ina260Sensor.hasSensor())
result = ina260Sensor.runOnce();
if (ina219Sensor.hasSensor())
result = ina219Sensor.runOnce();
if (shtc3Sensor.hasSensor())
result = shtc3Sensor.runOnce();
if (lps22hbSensor.hasSensor()) {
if (lps22hbSensor.hasSensor())
result = lps22hbSensor.runOnce();
}
if (sht31Sensor.hasSensor())
result = sht31Sensor.runOnce();
}
return result;
} else {
// if we somehow got to a second run of this module with measurement disabled, then just wait forever
if (!moduleConfig.telemetry.environment_measurement_enabled)
return result;
if (!moduleConfig.telemetry.environment_measurement_enabled) {
return disable();
} else {
if (bme680Sensor.hasSensor())
result = bme680Sensor.runTrigger();
}
uint32_t now = millis();
if (((lastSentToMesh == 0) ||
@ -107,13 +103,15 @@ int32_t EnvironmentTelemetryModule::runOnce()
airTime->isTxAllowedAirUtil()) {
sendTelemetry();
lastSentToMesh = now;
} else if (service.isToPhoneQueueEmpty()) {
} else if (((lastSentToPhone == 0) || ((now - lastSentToPhone) >= sendToPhoneIntervalMs)) &&
(service.isToPhoneQueueEmpty())) {
// Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected)
sendTelemetry(NODENUM_BROADCAST, true);
lastSentToPhone = now;
}
}
return sendToPhoneIntervalMs;
return min(sendToPhoneIntervalMs, result);
}
bool EnvironmentTelemetryModule::wantUIFrame()
@ -205,6 +203,7 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPac
bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
{
meshtastic_Telemetry m;
bool valid = false;
m.time = getTime();
m.which_variant = meshtastic_Telemetry_environment_metrics_tag;
@ -216,50 +215,52 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
m.variant.environment_metrics.voltage = 0;
if (sht31Sensor.hasSensor())
sht31Sensor.getMetrics(&m);
valid = sht31Sensor.getMetrics(&m);
if (lps22hbSensor.hasSensor())
lps22hbSensor.getMetrics(&m);
valid = lps22hbSensor.getMetrics(&m);
if (shtc3Sensor.hasSensor())
shtc3Sensor.getMetrics(&m);
valid = shtc3Sensor.getMetrics(&m);
if (bmp280Sensor.hasSensor())
bmp280Sensor.getMetrics(&m);
valid = bmp280Sensor.getMetrics(&m);
if (bme280Sensor.hasSensor())
bme280Sensor.getMetrics(&m);
valid = bme280Sensor.getMetrics(&m);
if (bme680Sensor.hasSensor())
bme680Sensor.getMetrics(&m);
valid = bme680Sensor.getMetrics(&m);
if (mcp9808Sensor.hasSensor())
mcp9808Sensor.getMetrics(&m);
valid = mcp9808Sensor.getMetrics(&m);
if (ina219Sensor.hasSensor())
ina219Sensor.getMetrics(&m);
valid = ina219Sensor.getMetrics(&m);
if (ina260Sensor.hasSensor())
ina260Sensor.getMetrics(&m);
valid = ina260Sensor.getMetrics(&m);
LOG_INFO(
"(Sending): barometric_pressure=%f, current=%f, gas_resistance=%f, relative_humidity=%f, temperature=%f, voltage=%f\n",
m.variant.environment_metrics.barometric_pressure, m.variant.environment_metrics.current,
m.variant.environment_metrics.gas_resistance, m.variant.environment_metrics.relative_humidity,
m.variant.environment_metrics.temperature, m.variant.environment_metrics.voltage);
if (valid) {
LOG_INFO("(Sending): barometric_pressure=%f, current=%f, gas_resistance=%f, relative_humidity=%f, temperature=%f, "
"voltage=%f\n",
m.variant.environment_metrics.barometric_pressure, m.variant.environment_metrics.current,
m.variant.environment_metrics.gas_resistance, m.variant.environment_metrics.relative_humidity,
m.variant.environment_metrics.temperature, m.variant.environment_metrics.voltage);
sensor_read_error_count = 0;
sensor_read_error_count = 0;
meshtastic_MeshPacket *p = allocDataProtobuf(m);
p->to = dest;
p->decoded.want_response = false;
if (config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR)
p->priority = meshtastic_MeshPacket_Priority_RELIABLE;
else
p->priority = meshtastic_MeshPacket_Priority_MIN;
// release previous packet before occupying a new spot
if (lastMeasurementPacket != nullptr)
packetPool.release(lastMeasurementPacket);
meshtastic_MeshPacket *p = allocDataProtobuf(m);
p->to = dest;
p->decoded.want_response = false;
if (config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR)
p->priority = meshtastic_MeshPacket_Priority_RELIABLE;
else
p->priority = meshtastic_MeshPacket_Priority_MIN;
// release previous packet before occupying a new spot
if (lastMeasurementPacket != nullptr)
packetPool.release(lastMeasurementPacket);
lastMeasurementPacket = packetPool.allocCopy(*p);
if (phoneOnly) {
LOG_INFO("Sending packet to phone\n");
service.sendToPhone(p);
} else {
LOG_INFO("Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true);
lastMeasurementPacket = packetPool.allocCopy(*p);
if (phoneOnly) {
LOG_INFO("Sending packet to phone\n");
service.sendToPhone(p);
} else {
LOG_INFO("Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true);
}
}
return true;
}
return valid;
}

Wyświetl plik

@ -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;
};

Wyświetl plik

@ -6,21 +6,41 @@
BME680Sensor::BME680Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BME680, "BME680") {}
int32_t BME680Sensor::runTrigger()
{
if (!bme680.run()) {
checkStatus("runTrigger");
}
return 35;
}
int32_t BME680Sensor::runOnce()
{
LOG_INFO("Init sensor: %s with the BSEC Library\n", sensorName);
if (!hasSensor()) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
bme680.begin(nodeTelemetrySensorsMap[sensorType], Wire);
if (!bme680.begin(nodeTelemetrySensorsMap[sensorType], Wire))
checkStatus("begin");
if (bme680.status == BSEC_OK) {
bme680.setConfig(Default_H2S_NonH2S_config);
loadState();
bme680.updateSubscription(sensorList, 13, BSEC_SAMPLE_RATE_LP);
status = 1;
if (!bme680.setConfig(bsec_config_iaq)) {
checkStatus("setConfig");
status = 0;
}
loadState();
if (!bme680.updateSubscription(sensorList, ARRAY_LEN(sensorList), BSEC_SAMPLE_RATE_LP)) {
checkStatus("updateSubscription");
status = 0;
}
LOG_INFO("Init sensor: %s with the BSEC Library version %d.%d.%d.%d \n", sensorName, bme680.version.major,
bme680.version.minor, bme680.version.major_bugfix, bme680.version.minor_bugfix);
} else {
status = 0;
}
if (status == 0)
LOG_DEBUG("BME680Sensor::runOnce: bme680.status %d\n", bme680.status);
return initI2CSensor();
}
@ -29,8 +49,8 @@ void BME680Sensor::setup() {}
bool BME680Sensor::getMetrics(meshtastic_Telemetry *measurement)
{
bme680.run();
if (bme680.getData(BSEC_OUTPUT_RAW_PRESSURE).signal == 0)
return false;
measurement->variant.environment_metrics.temperature = bme680.getData(BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE).signal;
measurement->variant.environment_metrics.relative_humidity =
bme680.getData(BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY).signal;
@ -106,4 +126,17 @@ void BME680Sensor::updateState()
#else
LOG_ERROR("ERROR: Filesystem not implemented\n");
#endif
}
}
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());
}

Wyświetl plik

@ -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;
};

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -1,8 +1,9 @@
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
#include "VoltageSensor.h"
#include <Adafruit_INA219.h>
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;
};

Wyświetl plik

@ -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());
}

Wyświetl plik

@ -1,8 +1,9 @@
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
#include "VoltageSensor.h"
#include <Adafruit_INA260.h>
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;
};

Wyświetl plik

@ -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;
};
};

Wyświetl plik

@ -0,0 +1,7 @@
#pragma once
class VoltageSensor
{
public:
virtual uint16_t getBusVoltageMv() = 0;
};

Wyświetl plik

@ -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};

Wyświetl plik

@ -0,0 +1,3 @@
#include <stdint.h>
extern const uint8_t bsec_config_iaq[1974];

Wyświetl plik

@ -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;

Wyświetl plik

@ -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();
}
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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];
}

Wyświetl plik

@ -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 <EEPROM.h>
//--------------------------------------------------------------------+
// 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;
}

Wyświetl plik

@ -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_ */

Wyświetl plik

@ -0,0 +1,258 @@
#include <Arduino.h>
#include <string.h>
#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

Wyświetl plik

@ -0,0 +1,85 @@
#ifndef LITTLEFS_H_
#define LITTLEFS_H_
#include <Stream.h>
#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_ */

Wyświetl plik

@ -0,0 +1,362 @@
#include <Arduino.h>
#include "LittleFS.h"
#include <lfs.h>
//--------------------------------------------------------------------+
// 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<int>(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<int>(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();
}

Wyświetl plik

@ -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_ */

Wyświetl plik

@ -6,24 +6,19 @@
// defaults for STM32WL architecture
//
#ifndef HAS_RADIO
#define HAS_RADIO 1
#endif
//
// set HW_VENDOR
//
#ifndef HW_VENDOR
#define HW_VENDOR HardwareModel_PRIVATE_HW
#define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW
#endif
#ifdef __cplusplus
extern "C" {
#endif
void stm32wl_emulate_digitalWrite(long unsigned int pin, long unsigned int value);
int stm32wl_emulate_digitalRead(long unsigned int pin);
#ifdef __cplusplus
}
#endif
/* virtual pins for stm32wl_emulate_digitalWrite() / stm32wl_emulate_digitalRead() to recognize */
/* virtual pins */
#define SX126X_CS 1000
#define SX126X_DIO1 1001
#define SX126X_RESET 1003

Wyświetl plik

@ -1,65 +0,0 @@
#include "architecture.h"
#include "stm32wlxx.h"
#include "stm32wlxx_hal.h"
#include <stdbool.h>
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;
}

Wyświetl plik

@ -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) {}

Wyświetl plik

@ -22,6 +22,13 @@ extern RTC_NOINIT_ATTR uint64_t RTC_reg_b;
#include "soc/sens_reg.h" // needed for adc pin reset
#endif
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO)
#include "modules/Telemetry/Sensor/INA219Sensor.h"
#include "modules/Telemetry/Sensor/INA260Sensor.h"
extern INA260Sensor ina260Sensor;
extern INA219Sensor ina219Sensor;
#endif
class Power : private concurrency::OSThread
{
@ -41,7 +48,6 @@ class Power : private concurrency::OSThread
/// Setup a xpowers chip axp192/axp2101, return true if found
bool axpChipInit();
/// Setup a simple ADC input based battery sensor
bool analogInit();

Wyświetl plik

@ -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");

Wyświetl plik

@ -103,13 +103,13 @@ void setGPSPower(bool on)
if (pmu_found && PMU) {
uint8_t model = PMU->getChipModel();
if (model == XPOWERS_AXP2101) {
#if (HW_VENDOR == meshtastic_HardwareModel_TBEAM)
// t-beam v1.2 GNSS power channel
on ? PMU->enablePowerOutput(XPOWERS_ALDO3) : PMU->disablePowerOutput(XPOWERS_ALDO3);
#elif (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE)
// t-beam-s3-core GNSS power channel
on ? PMU->enablePowerOutput(XPOWERS_ALDO4) : PMU->disablePowerOutput(XPOWERS_ALDO4);
#endif
if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) {
// t-beam v1.2 GNSS power channel
on ? PMU->enablePowerOutput(XPOWERS_ALDO3) : PMU->disablePowerOutput(XPOWERS_ALDO3);
} else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) {
// t-beam-s3-core GNSS power channel
on ? PMU->enablePowerOutput(XPOWERS_ALDO4) : PMU->disablePowerOutput(XPOWERS_ALDO4);
}
} else if (model == XPOWERS_AXP192) {
// t-beam v1.1 GNSS power channel
on ? PMU->enablePowerOutput(XPOWERS_LDO3) : PMU->disablePowerOutput(XPOWERS_LDO3);
@ -252,12 +252,12 @@ void doDeepSleep(uint32_t msecToWake)
uint8_t model = PMU->getChipModel();
if (model == XPOWERS_AXP2101) {
#if (HW_VENDOR == meshtastic_HardwareModel_TBEAM)
// t-beam v1.2 radio power channel
PMU->disablePowerOutput(XPOWERS_ALDO2); // lora radio power channel
#elif (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE)
PMU->disablePowerOutput(XPOWERS_ALDO3); // lora radio power channel
#endif
if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) {
// t-beam v1.2 radio power channel
PMU->disablePowerOutput(XPOWERS_ALDO2); // lora radio power channel
} else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) {
PMU->disablePowerOutput(XPOWERS_ALDO3); // lora radio power channel
}
} else if (model == XPOWERS_AXP192) {
// t-beam v1.1 radio power channel
PMU->disablePowerOutput(XPOWERS_LDO2); // lora radio power channel

Wyświetl plik

@ -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;

Wyświetl plik

@ -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

Wyświetl plik

@ -9,6 +9,7 @@
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
#define ADC_MULTIPLIER 4.9
#define USE_SX1262

Wyświetl plik

@ -10,6 +10,7 @@
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
#define ADC_MULTIPLIER 4.9
#define USE_SX1262

Wyświetl plik

@ -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;

Some files were not shown because too many files have changed in this diff Show More