mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-13 07:01:18 +10:00
Compare commits
41
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
404d0dda79 | ||
|
|
514c19a68e | ||
|
|
1085b54069 | ||
|
|
bcbc2f229d | ||
|
|
74b90d3505 | ||
|
|
d246c47ae7 | ||
|
|
54e52ae05f | ||
|
|
8130b1cf43 | ||
|
|
9d4c4f8bd1 | ||
|
|
3b0169ba7a | ||
|
|
996e72a816 | ||
|
|
a40b4e4d69 | ||
|
|
f4151a7108 | ||
|
|
a3755dfce5 | ||
|
|
ca5795d3e7 | ||
|
|
990ee5dacf | ||
|
|
4c55d5d9e4 | ||
|
|
7db02ad722 | ||
|
|
7f7c5cbd62 | ||
|
|
0c0a3c4b55 | ||
|
|
bf762bc58d | ||
|
|
84e578323e | ||
|
|
bdbe42dfd0 | ||
|
|
4f64c4f7b9 | ||
|
|
af5ac32048 | ||
|
|
9586c68c65 | ||
|
|
ca45888f3e | ||
|
|
1e4ecea6fc | ||
|
|
d1ea589757 | ||
|
|
af52dcecdf | ||
|
|
0ae4622393 | ||
|
|
a49740cd56 | ||
|
|
417feee47f | ||
|
|
d604a76c73 | ||
|
|
ac9c5f81b9 | ||
|
|
d6fa190025 | ||
|
|
f2c04c5504 | ||
|
|
4ae5443c3b | ||
|
|
6b5101ec67 | ||
|
|
062c646814 | ||
|
|
bccc0d47eb |
@@ -64,6 +64,7 @@ jobs:
|
||||
- board: tlora-v1
|
||||
- board: tlora_v1_3
|
||||
- board: tlora-v2-1-1_6
|
||||
- board: tlora-v2-1-1_6-tcxo
|
||||
- board: tlora-v2-1-1_8
|
||||
- board: tbeam
|
||||
- board: heltec-ht62-esp32c3-sx1262
|
||||
@@ -79,6 +80,7 @@ jobs:
|
||||
- board: m5stack-core
|
||||
- board: m5stack-coreink
|
||||
- board: nano-g1-explorer
|
||||
- board: chatter2
|
||||
uses: ./.github/workflows/build_esp32.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
@@ -245,7 +247,7 @@ jobs:
|
||||
id: version
|
||||
|
||||
- name: Move files up
|
||||
run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./*tbeam-s3*/bleota-s3.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat ./firmware-raspbian-*/release/meshtasticd_linux_aarch64 ./firmware-raspbian-*/bin/config-dist.yaml
|
||||
run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./*tbeam-s3*/bleota-s3.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase_v2.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat ./firmware-raspbian-*/release/meshtasticd_linux_aarch64 ./firmware-raspbian-*/bin/config-dist.yaml
|
||||
|
||||
- name: Repackage in single firmware zip
|
||||
uses: actions/upload-artifact@v3
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
|
||||
[portduino_base]
|
||||
platform = https://github.com/meshtastic/platform-native.git#04435d06e39916a6c019d511518d8e95c659dfbd
|
||||
platform = https://github.com/meshtastic/platform-native.git#a28dd5a9ccd5c48a9bede46037855ff83915d74b
|
||||
framework = arduino
|
||||
|
||||
build_src_filter =
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -60,6 +60,11 @@ GPIO:
|
||||
GPS:
|
||||
# SerialPath: /dev/ttyS0
|
||||
|
||||
### Specify I2C device, or leave blank for none
|
||||
|
||||
I2C:
|
||||
# I2CDevice: /dev/i2c-1
|
||||
|
||||
### Set up SPI displays here. Note that I2C displays are generally auto-detected.
|
||||
|
||||
Display:
|
||||
@@ -86,7 +91,19 @@ Display:
|
||||
# OffsetX: 0
|
||||
# OffsetY: 0
|
||||
|
||||
### Adafruit PiTFT 2.8 TFT+Touchscreen
|
||||
# Panel: ILI9341
|
||||
# CS: 8
|
||||
# DC: 25
|
||||
# Backlight: 2
|
||||
# Width: 320
|
||||
# Height: 240
|
||||
|
||||
Touchscreen:
|
||||
# Module: STMPE610
|
||||
# CS: 7
|
||||
# IRQ: 24
|
||||
|
||||
# Module: XPT2046
|
||||
# CS: 7
|
||||
# IRQ: 17
|
||||
@@ -95,3 +112,8 @@ Touchscreen:
|
||||
|
||||
Input:
|
||||
# KeyboardDevice: /dev/input/event0
|
||||
|
||||
###
|
||||
|
||||
Logging:
|
||||
LogLevel: info # debug, info, warn, error
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [
|
||||
["0x239A", "0x4405"],
|
||||
["0x239A", "0x0029"],
|
||||
["0x239A", "0x002A"]
|
||||
],
|
||||
"usb_product": "TTGO_eink",
|
||||
|
||||
+3
-1
@@ -10,10 +10,12 @@ default_envs = tbeam
|
||||
;default_envs = heltec-v2_0
|
||||
;default_envs = heltec-v2_1
|
||||
;default_envs = heltec-wireless-tracker
|
||||
;default_envs = chatter2
|
||||
;default_envs = tlora-v1
|
||||
;default_envs = tlora_v1_3
|
||||
;default_envs = tlora-v2
|
||||
;default_envs = tlora-v2-1-1_6
|
||||
;default_envs = tlora-v2-1-1_6-tcxo
|
||||
;default_envs = tlora-t3s3-v1
|
||||
;default_envs = lora-relay-v1 # nrf board
|
||||
;default_envs = t-echo
|
||||
@@ -73,7 +75,7 @@ lib_deps =
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#ee628ee6c9588d4c56c9e3da35f0fc9448ad54a8 ; ESP8266_SSD1306
|
||||
mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce
|
||||
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#076e8d2c8fb702d9be5b08c55b93ff76f8af7e61
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#2044b2c51e91ab4cd8cc93b15e40658cd808dd06
|
||||
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
|
||||
nanopb/Nanopb@^0.4.7
|
||||
erriez/ErriezCRC32@^1.0.1
|
||||
|
||||
+1
-1
Submodule protobufs updated: 44e369e181...99bd42baf8
+18
-14
@@ -54,15 +54,18 @@ class ButtonThread : public concurrency::OSThread
|
||||
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
|
||||
userButton = OneButton(settingsMap[user], true, true);
|
||||
#elif defined(BUTTON_PIN)
|
||||
|
||||
userButton = OneButton(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, true, true);
|
||||
int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN;
|
||||
userButton = OneButton(pin, true, true);
|
||||
#endif
|
||||
|
||||
#ifdef INPUT_PULLUP_SENSE
|
||||
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
||||
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP_SENSE);
|
||||
pinMode(pin, INPUT_PULLUP_SENSE);
|
||||
#endif
|
||||
userButton.attachClick(userButtonPressed);
|
||||
userButton.setClickMs(300);
|
||||
userButton.setClickMs(400);
|
||||
userButton.setPressMs(1000);
|
||||
userButton.setDebounceMs(10);
|
||||
userButton.attachDuringLongPress(userButtonPressedLong);
|
||||
userButton.attachDoubleClick(userButtonDoublePressed);
|
||||
userButton.attachMultiClick(userButtonMultiPressed);
|
||||
@@ -72,7 +75,15 @@ class ButtonThread : public concurrency::OSThread
|
||||
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
|
||||
wakeOnIrq(settingsMap[user], FALLING);
|
||||
#else
|
||||
wakeOnIrq(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, FALLING);
|
||||
static OneButton *pBtn = &userButton; // only one instance of ButtonThread is created, so static is safe
|
||||
attachInterrupt(
|
||||
pin,
|
||||
[]() {
|
||||
BaseType_t higherWake = 0;
|
||||
mainDelay.interruptFromISR(&higherWake);
|
||||
pBtn->tick();
|
||||
},
|
||||
CHANGE);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef BUTTON_PIN_ALT
|
||||
@@ -193,15 +204,8 @@ class ButtonThread : public concurrency::OSThread
|
||||
static void userButtonMultiPressed()
|
||||
{
|
||||
if (!config.device.disable_triple_click && (gps != nullptr)) {
|
||||
config.position.gps_enabled = !(config.position.gps_enabled);
|
||||
if (config.position.gps_enabled) {
|
||||
LOG_DEBUG("Flag set to true to restore power\n");
|
||||
gps->enable();
|
||||
|
||||
} else {
|
||||
LOG_DEBUG("Flag set to false for gps power\n");
|
||||
gps->disable();
|
||||
}
|
||||
gps->toggleGpsMode();
|
||||
screen->forceDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-7
@@ -10,12 +10,12 @@ template <class T> class Observable;
|
||||
*/
|
||||
template <class T> class Observer
|
||||
{
|
||||
std::list<Observable<T> *> observed;
|
||||
std::list<Observable<T> *> observables;
|
||||
|
||||
public:
|
||||
virtual ~Observer();
|
||||
|
||||
/// Stop watching the obserable
|
||||
/// Stop watching the observable
|
||||
void unobserve(Observable<T> *o);
|
||||
|
||||
/// Start watching a specified observable
|
||||
@@ -86,21 +86,21 @@ template <class T> class Observable
|
||||
|
||||
template <class T> Observer<T>::~Observer()
|
||||
{
|
||||
for (typename std::list<Observable<T> *>::const_iterator iterator = observed.begin(); iterator != observed.end();
|
||||
for (typename std::list<Observable<T> *>::const_iterator iterator = observables.begin(); iterator != observables.end();
|
||||
++iterator) {
|
||||
(*iterator)->removeObserver(this);
|
||||
}
|
||||
observed.clear();
|
||||
observables.clear();
|
||||
}
|
||||
|
||||
template <class T> void Observer<T>::unobserve(Observable<T> *o)
|
||||
{
|
||||
o->removeObserver(this);
|
||||
observed.remove(o);
|
||||
observables.remove(o);
|
||||
}
|
||||
|
||||
template <class T> void Observer<T>::observe(Observable<T> *o)
|
||||
{
|
||||
observed.push_back(o);
|
||||
observables.push_back(o);
|
||||
o->addObserver(this);
|
||||
}
|
||||
}
|
||||
+55
-51
@@ -164,7 +164,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
#endif
|
||||
|
||||
#ifndef BATTERY_SENSE_SAMPLES
|
||||
#define BATTERY_SENSE_SAMPLES 30
|
||||
#define BATTERY_SENSE_SAMPLES \
|
||||
30 // Set the number of samples, it has an effect of increasing sensitivity in complex electromagnetic environment.
|
||||
#endif
|
||||
|
||||
#ifdef BATTERY_PIN
|
||||
@@ -176,66 +177,71 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
if (millis() - last_read_time_ms > min_read_interval) {
|
||||
last_read_time_ms = millis();
|
||||
|
||||
// Set the number of samples, it has an effect of increasing sensitivity, especially in complex electromagnetic
|
||||
// environment.
|
||||
uint32_t raw = 0;
|
||||
#ifdef ARCH_ESP32
|
||||
#ifndef BAT_MEASURE_ADC_UNIT // ADC1
|
||||
#ifdef ADC_CTRL
|
||||
if (heltec_version == 5) {
|
||||
pinMode(ADC_CTRL, OUTPUT);
|
||||
digitalWrite(ADC_CTRL, HIGH);
|
||||
delay(10);
|
||||
}
|
||||
#endif
|
||||
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
|
||||
raw += adc1_get_raw(adc_channel);
|
||||
}
|
||||
#ifdef ADC_CTRL
|
||||
if (heltec_version == 5) {
|
||||
digitalWrite(ADC_CTRL, LOW);
|
||||
}
|
||||
#endif
|
||||
#else // ADC2
|
||||
int32_t adc_buf = 0;
|
||||
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
|
||||
// ADC2 wifi bug workaround, see
|
||||
// https://github.com/espressif/arduino-esp32/issues/102
|
||||
WRITE_PERI_REG(SENS_SAR_READ_CTRL2_REG, RTC_reg_b);
|
||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DATA_INV);
|
||||
adc2_get_raw(adc_channel, ADC_WIDTH_BIT_12, &adc_buf);
|
||||
raw += adc_buf;
|
||||
}
|
||||
#endif // BAT_MEASURE_ADC_UNIT
|
||||
#else // !ARCH_ESP32
|
||||
float scaled = 0;
|
||||
|
||||
#ifdef ARCH_ESP32 // ADC block for espressif platforms
|
||||
raw = espAdcRead();
|
||||
scaled = esp_adc_cal_raw_to_voltage(raw, adc_characs);
|
||||
scaled *= operativeAdcMultiplier;
|
||||
#else // block for all other platforms
|
||||
for (uint32_t i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
|
||||
raw += analogRead(BATTERY_PIN);
|
||||
}
|
||||
#endif
|
||||
raw = raw / BATTERY_SENSE_SAMPLES;
|
||||
float scaled;
|
||||
#ifdef ARCH_ESP32
|
||||
scaled = esp_adc_cal_raw_to_voltage(raw, adc_characs);
|
||||
scaled *= operativeAdcMultiplier;
|
||||
#else
|
||||
#ifndef VBAT_RAW_TO_SCALED
|
||||
scaled = 1000.0 * operativeAdcMultiplier * (AREF_VOLTAGE / 1024.0) * raw;
|
||||
#else
|
||||
scaled = VBAT_RAW_TO_SCALED(raw); // defined in variant.h
|
||||
#endif // VBAT RAW TO SCALED
|
||||
#endif // ARCH_ESP32
|
||||
// LOG_DEBUG("battery gpio %d raw val=%u scaled=%u\n", BATTERY_PIN, raw, (uint32_t)(scaled));
|
||||
|
||||
scaled = operativeAdcMultiplier * ((1000 * AREF_VOLTAGE) / pow(2, BATTERY_SENSE_RESOLUTION_BITS)) * raw;
|
||||
#endif
|
||||
// LOG_DEBUG("battery gpio %d raw val=%u scaled=%u\n", BATTERY_PIN, raw, (uint32_t)(scaled));
|
||||
last_read_value = scaled;
|
||||
return scaled;
|
||||
} else {
|
||||
return last_read_value;
|
||||
}
|
||||
#else
|
||||
return 0;
|
||||
#endif // BATTERY_PIN
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(ARCH_ESP32) && !defined(HAS_PMU) && defined(BATTERY_PIN)
|
||||
/**
|
||||
* ESP32 specific function for getting calibrated ADC reads
|
||||
*/
|
||||
uint32_t espAdcRead()
|
||||
{
|
||||
|
||||
uint32_t raw = 0;
|
||||
|
||||
#ifndef BAT_MEASURE_ADC_UNIT // ADC1
|
||||
#ifdef ADC_CTRL
|
||||
if (heltec_version == 5) {
|
||||
pinMode(ADC_CTRL, OUTPUT);
|
||||
digitalWrite(ADC_CTRL, HIGH);
|
||||
delay(10);
|
||||
}
|
||||
#endif
|
||||
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
|
||||
raw += adc1_get_raw(adc_channel);
|
||||
}
|
||||
#ifdef ADC_CTRL
|
||||
if (heltec_version == 5) {
|
||||
digitalWrite(ADC_CTRL, LOW);
|
||||
}
|
||||
#endif
|
||||
#else // ADC2
|
||||
int32_t adc_buf = 0;
|
||||
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
|
||||
// ADC2 wifi bug workaround, see
|
||||
// https://github.com/espressif/arduino-esp32/issues/102
|
||||
WRITE_PERI_REG(SENS_SAR_READ_CTRL2_REG, RTC_reg_b);
|
||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DATA_INV);
|
||||
adc2_get_raw(adc_channel, ADC_WIDTH_BIT_12, &adc_buf);
|
||||
raw += adc_buf;
|
||||
}
|
||||
#endif // BAT_MEASURE_ADC_UNIT
|
||||
raw = raw / BATTERY_SENSE_SAMPLES;
|
||||
return raw;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* return true if there is a battery installed in this unit
|
||||
*/
|
||||
@@ -383,10 +389,8 @@ bool Power::analogInit()
|
||||
#else
|
||||
analogReference(AR_INTERNAL); // 3.6V
|
||||
#endif
|
||||
analogReadResolution(BATTERY_SENSE_RESOLUTION_BITS); // Default of 12 is not very linear. Recommended to use 10 or 11
|
||||
// depending on needed resolution.
|
||||
|
||||
#endif // ARCH_NRF52
|
||||
analogReadResolution(BATTERY_SENSE_RESOLUTION_BITS);
|
||||
|
||||
batteryLevel = &analogLevel;
|
||||
return true;
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#include "platform/portduino/PortduinoGlue.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A printer that doesn't go anywhere
|
||||
*/
|
||||
@@ -68,7 +72,15 @@ 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) {
|
||||
#ifdef ARCH_PORTDUINO
|
||||
if (settingsMap[logoutputlevel] < level_debug && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
|
||||
return 0;
|
||||
else if (settingsMap[logoutputlevel] < level_info && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
|
||||
return 0;
|
||||
else if (settingsMap[logoutputlevel] < level_warn && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0)
|
||||
return 0;
|
||||
#endif
|
||||
if (moduleConfig.serial.override_console_serial_port && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) {
|
||||
return 0;
|
||||
}
|
||||
size_t r = 0;
|
||||
|
||||
+155
-113
@@ -16,7 +16,7 @@
|
||||
#define GPS_RESET_MODE HIGH
|
||||
#endif
|
||||
|
||||
#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(aLinuxInputImpl)
|
||||
#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
|
||||
HardwareSerial *GPS::_serial_gps = &Serial1;
|
||||
#else
|
||||
HardwareSerial *GPS::_serial_gps = NULL;
|
||||
@@ -251,17 +251,9 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
|
||||
bool GPS::setup()
|
||||
{
|
||||
int msglen = 0;
|
||||
bool isProblematicGPS = false;
|
||||
|
||||
if (!didSerialInit) {
|
||||
#if !defined(GPS_UC6580)
|
||||
#ifdef HAS_PMU
|
||||
// The T-Beam 1.2 has issues with the GPS
|
||||
if (HW_VENDOR == meshtastic_HardwareModel_TBEAM && PMU->getChipModel() == XPOWERS_AXP2101) {
|
||||
gnssModel = GNSS_MODEL_UBLOX;
|
||||
isProblematicGPS = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(RAK4630) && defined(PIN_3V3_EN)
|
||||
// If we are using the RAK4630 and we have no other peripherals on the I2C bus or module interest in 3V3_S,
|
||||
@@ -334,125 +326,158 @@ bool GPS::setup()
|
||||
// Also we need SBAS for better accuracy and extra features
|
||||
// ToDo: Dynamic configure GNSS systems depending of LoRa region
|
||||
|
||||
if (strncmp(info.hwVersion, "00040007", 8) !=
|
||||
0) { // The original ublox 6 is GPS only and doesn't support the UBX-CFG-GNSS message
|
||||
if (strncmp(info.hwVersion, "00070000", 8) == 0) { // Max7 seems to only support GPS *or* GLONASS
|
||||
LOG_DEBUG("Setting GPS+SBAS\n");
|
||||
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_7), _message_GNSS_7);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
} else {
|
||||
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS), _message_GNSS);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
}
|
||||
if (strncmp(info.hwVersion, "000A0000", 8) != 0) {
|
||||
if (strncmp(info.hwVersion, "00040007", 8) != 0) {
|
||||
// The original ublox Neo-6 is GPS only and doesn't support the UBX-CFG-GNSS message
|
||||
// Max7 seems to only support GPS *or* GLONASS
|
||||
// Neo-7 is supposed to support GPS *and* GLONASS but NAKs the CFG-GNSS command to do it
|
||||
// So treat all the u-blox 7 series as GPS only
|
||||
// M8 can support 3 constallations at once so turn on GPS, GLONASS and Galileo (or BeiDou)
|
||||
|
||||
if (getACK(0x06, 0x3e, 800) == GNSS_RESPONSE_NAK) {
|
||||
// It's not critical if the module doesn't acknowledge this configuration.
|
||||
LOG_INFO("Unable to reconfigure GNSS - defaults maintained. Is this module GPS-only?\n");
|
||||
} else {
|
||||
if (strncmp(info.hwVersion, "00070000", 8) == 0) {
|
||||
LOG_INFO("GNSS configured for GPS+SBAS. Pause for 0.75s before sending next command.\n");
|
||||
LOG_DEBUG("Setting GPS+SBAS\n");
|
||||
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_7), _message_GNSS_7);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
} else {
|
||||
LOG_INFO("GNSS configured for GPS+SBAS+GLONASS. Pause for 0.75s before sending next command.\n");
|
||||
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_8), _message_GNSS_8);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
}
|
||||
|
||||
if (getACK(0x06, 0x3e, 800) == GNSS_RESPONSE_NAK) {
|
||||
// It's not critical if the module doesn't acknowledge this configuration.
|
||||
LOG_INFO("Unable to reconfigure GNSS - defaults maintained. Is this module GPS-only?\n");
|
||||
} else {
|
||||
if (strncmp(info.hwVersion, "00070000", 8) == 0) {
|
||||
LOG_INFO("GNSS configured for GPS+SBAS. Pause for 0.75s before sending next command.\n");
|
||||
} else {
|
||||
LOG_INFO(
|
||||
"GNSS configured for GPS+SBAS+GLONASS+Galileo. Pause for 0.75s before sending next command.\n");
|
||||
}
|
||||
// Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next
|
||||
// commands for the M8 it tends to be more... 1 sec should be enough ;>)
|
||||
delay(1000);
|
||||
}
|
||||
// Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next
|
||||
// commands
|
||||
delay(750);
|
||||
}
|
||||
}
|
||||
// ToDo add M10 tests for below
|
||||
if (strncmp(info.hwVersion, "00080000", 8) == 0) {
|
||||
msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM_8), _message_JAM_8);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x39, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable interference resistance.\n");
|
||||
}
|
||||
clearBuffer();
|
||||
msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5_8), _message_NAVX5_8);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x23, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to configure extra settings.\n");
|
||||
}
|
||||
} else {
|
||||
msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM_6_7), _message_JAM_6_7);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x39, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable interference resistance.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM), _message_JAM);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x39, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable interference resistance.\n");
|
||||
}
|
||||
msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5), _message_NAVX5);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x23, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to configure extra settings.\n");
|
||||
}
|
||||
}
|
||||
// ublox-M10S can be compatible with UBLOX traditional protocol, so the following sentence settings are also valid
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5), _message_NAVX5);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x23, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to configure extra settings.\n");
|
||||
}
|
||||
|
||||
// ublox-M10S can be compatible with UBLOX traditional protocol, so the following sentence settings are also valid
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x08, sizeof(_message_1HZ), _message_1HZ);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x08, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to set GPS update rate.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GGL), _message_GGL);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable NMEA GGL.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSA), _message_GSA);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to Enable NMEA GSA.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSV), _message_GSV);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable NMEA GSV.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_VTG), _message_VTG);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable NMEA VTG.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_RMC), _message_RMC);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable NMEA RMC.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GGA), _message_GGA);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable NMEA GGA.\n");
|
||||
}
|
||||
|
||||
if (uBloxProtocolVersion >= 18) {
|
||||
msglen = makeUBXPacket(0x06, 0x86, sizeof(_message_PMS), _message_PMS);
|
||||
msglen = makeUBXPacket(0x06, 0x08, sizeof(_message_1HZ), _message_1HZ);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x86, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving for GPS.\n");
|
||||
if (getACK(0x06, 0x08, 400) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to set GPS update rate.\n");
|
||||
}
|
||||
} else {
|
||||
if (!(isProblematicGPS)) {
|
||||
if (strncmp(info.hwVersion, "00040007", 8) == 0) { // This PSM mode has only been tested on this hardware
|
||||
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_PSM);
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GLL), _message_GLL);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable NMEA GLL.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSA), _message_GSA);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to Enable NMEA GSA.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSV), _message_GSV);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable NMEA GSV.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_VTG), _message_VTG);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable NMEA VTG.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_RMC), _message_RMC);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable NMEA RMC.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GGA), _message_GGA);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable NMEA GGA.\n");
|
||||
}
|
||||
clearBuffer();
|
||||
if (uBloxProtocolVersion >= 18) {
|
||||
msglen = makeUBXPacket(0x06, 0x86, sizeof(_message_PMS), _message_PMS);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x86, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving for GPS.\n");
|
||||
}
|
||||
// For M8 we want to enable NMEA vserion 4.10 so we can see the additional sats.
|
||||
if (strncmp(info.hwVersion, "00080000", 8) == 0) {
|
||||
msglen = makeUBXPacket(0x06, 0x17, sizeof(_message_NMEA), _message_NMEA);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x17, 400) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable NMEA 4.10.\n");
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (strncmp(info.hwVersion, "00040007", 8) == 0) { // This PSM mode is only for Neo-6
|
||||
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_ECO);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x11, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving mode for GPS.\n");
|
||||
LOG_WARN("Unable to enable powersaving ECO mode for Neo-6.\n");
|
||||
}
|
||||
msglen = makeUBXPacket(0x06, 0x3B, 44, _message_CFG_PM2);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x3B, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving details for GPS.\n");
|
||||
}
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_AID), _message_AID);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable UBX-AID.\n");
|
||||
}
|
||||
} else {
|
||||
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_ECO);
|
||||
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_PSM);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x11, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving ECO mode for GPS.\n");
|
||||
LOG_WARN("Unable to enable powersaving mode for GPS.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// The T-beam 1.2 has issues.
|
||||
if (!(isProblematicGPS)) {
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE), _message_SAVE);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x09, 300) != GNSS_RESPONSE_OK) {
|
||||
if (getACK(0x06, 0x09, 2000) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to save GNSS module configuration.\n");
|
||||
} else {
|
||||
LOG_INFO("GNSS module configuration saved!\n");
|
||||
}
|
||||
} else {
|
||||
LOG_INFO("u-blox M10 hardware found, using defaults for now\n");
|
||||
}
|
||||
}
|
||||
didSerialInit = true;
|
||||
@@ -611,7 +636,7 @@ uint32_t GPS::getSleepTime() const
|
||||
uint32_t t = config.position.gps_update_interval;
|
||||
|
||||
// We'll not need the GPS thread to wake up again after first acq. with fixed position.
|
||||
if (!config.position.gps_enabled || config.position.fixed_position)
|
||||
if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED || config.position.fixed_position)
|
||||
t = UINT32_MAX; // Sleep forever now
|
||||
|
||||
if (t == UINT32_MAX)
|
||||
@@ -632,21 +657,24 @@ void GPS::publishUpdate()
|
||||
// Notify any status instances that are observing us
|
||||
const meshtastic::GPSStatus status = meshtastic::GPSStatus(hasValidLocation, isConnected(), isPowerSaving(), p);
|
||||
newStatus.notifyObservers(&status);
|
||||
if (config.position.gps_enabled)
|
||||
if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
||||
positionModule->handleNewPosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t GPS::runOnce()
|
||||
{
|
||||
if (!GPSInitFinished) {
|
||||
if (!_serial_gps)
|
||||
if (!_serial_gps || config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) {
|
||||
LOG_INFO("GPS set to not-present. Skipping probe.\n");
|
||||
return disable();
|
||||
}
|
||||
if (!setup())
|
||||
return 2000; // Setup failed, re-run in two seconds
|
||||
|
||||
// We have now loaded our saved preferences from flash
|
||||
if (config.position.gps_enabled == false) {
|
||||
if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
||||
return disable();
|
||||
}
|
||||
// ONCE we will factory reset the GPS for bug #327
|
||||
@@ -669,7 +697,7 @@ int32_t GPS::runOnce()
|
||||
// if we have received valid NMEA claim we are connected
|
||||
setConnected();
|
||||
} else {
|
||||
if ((config.position.gps_enabled == 1) && (gnssModel == GNSS_MODEL_UBLOX)) {
|
||||
if ((config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) && (gnssModel == GNSS_MODEL_UBLOX)) {
|
||||
// reset the GPS on next bootup
|
||||
if (devicestate.did_gps_reset && (millis() - lastWakeStartMsec > 60000) && !hasFlow()) {
|
||||
LOG_DEBUG("GPS is not communicating, trying factory reset on next bootup.\n");
|
||||
@@ -682,7 +710,8 @@ int32_t GPS::runOnce()
|
||||
// At least one GPS has a bad habit of losing its mind from time to time
|
||||
if (rebootsSeen > 2) {
|
||||
rebootsSeen = 0;
|
||||
gps->factoryReset();
|
||||
LOG_DEBUG("Would normally factoryReset()\n");
|
||||
// gps->factoryReset();
|
||||
}
|
||||
|
||||
// If we are overdue for an update, turn on the GPS and at least publish the current status
|
||||
@@ -881,9 +910,9 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
strncpy((char *)buffer, &(info.extension[i][4]), sizeof(buffer));
|
||||
// LOG_DEBUG("GetModel:%s\n", (char *)buffer);
|
||||
if (strlen((char *)buffer)) {
|
||||
LOG_INFO("UBlox GNSS init succeeded, using UBlox %s GNSS Module\n", (char *)buffer);
|
||||
LOG_INFO("UBlox GNSS probe succeeded, using UBlox %s GNSS Module\n", (char *)buffer);
|
||||
} else {
|
||||
LOG_INFO("UBlox GNSS init succeeded, using UBlox GNSS Module\n");
|
||||
LOG_INFO("UBlox GNSS probe succeeded, using UBlox GNSS Module\n");
|
||||
}
|
||||
} else if (!strncmp(info.extension[i], "PROTVER", 7)) {
|
||||
char *ptr = nullptr;
|
||||
@@ -908,7 +937,7 @@ GPS *GPS::createGps()
|
||||
int8_t _rx_gpio = config.position.rx_gpio;
|
||||
int8_t _tx_gpio = config.position.tx_gpio;
|
||||
int8_t _en_gpio = config.position.gps_en_gpio;
|
||||
#if defined(HAS_GPS) && !defined(ARCH_ESP32)
|
||||
#if HAS_GPS && !defined(ARCH_ESP32)
|
||||
_rx_gpio = 1; // We only specify GPS serial ports on ESP32. Otherwise, these are just flags.
|
||||
_tx_gpio = 1;
|
||||
#endif
|
||||
@@ -1104,7 +1133,7 @@ bool GPS::lookForLocation()
|
||||
|
||||
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
fixType = atoi(gsafixtype.value()); // will set to zero if no data
|
||||
// LOG_DEBUG("FIX QUAL=%d, TYPE=%d\n", fixQual, fixType);
|
||||
// LOG_DEBUG("FIX QUAL=%d, TYPE=%d\n", fixQual, fixType);
|
||||
#endif
|
||||
|
||||
// check if GPS has an acceptable lock
|
||||
@@ -1121,6 +1150,10 @@ bool GPS::lookForLocation()
|
||||
reader.date.age(), reader.time.age());
|
||||
#endif // GPS_EXTRAVERBOSE
|
||||
|
||||
// Is this a new point or are we re-reading the previous one?
|
||||
if (!reader.location.isUpdated())
|
||||
return false;
|
||||
|
||||
// check if a complete GPS solution set is available for reading
|
||||
// tinyGPSDatum::age() also includes isValid() test
|
||||
// FIXME
|
||||
@@ -1133,10 +1166,6 @@ bool GPS::lookForLocation()
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is this a new point or are we re-reading the previous one?
|
||||
if (!reader.location.isUpdated())
|
||||
return false;
|
||||
|
||||
// We know the solution is fresh and valid, so just read the data
|
||||
auto loc = reader.location.value();
|
||||
|
||||
@@ -1286,4 +1315,17 @@ int32_t GPS::disable()
|
||||
setAwake(false);
|
||||
|
||||
return INT32_MAX;
|
||||
}
|
||||
|
||||
void GPS::toggleGpsMode()
|
||||
{
|
||||
if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
||||
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_DISABLED;
|
||||
LOG_DEBUG("Flag set to false for gps power. GpsMode: DISABLED\n");
|
||||
disable();
|
||||
} else if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_DISABLED) {
|
||||
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED;
|
||||
LOG_DEBUG("Flag set to true to restore power. GpsMode: ENABLED\n");
|
||||
enable();
|
||||
}
|
||||
}
|
||||
+12
-4
@@ -95,19 +95,24 @@ class GPS : private concurrency::OSThread
|
||||
static HardwareSerial *_serial_gps;
|
||||
|
||||
static uint8_t _message_PMREQ[];
|
||||
static uint8_t _message_PMREQ_10[];
|
||||
static const uint8_t _message_CFG_RXM_PSM[];
|
||||
static const uint8_t _message_CFG_RXM_ECO[];
|
||||
static const uint8_t _message_CFG_PM2[];
|
||||
static const uint8_t _message_GNSS_7[];
|
||||
static const uint8_t _message_GNSS[];
|
||||
static const uint8_t _message_JAM[];
|
||||
static const uint8_t _message_GNSS_8[];
|
||||
static const uint8_t _message_JAM_6_7[];
|
||||
static const uint8_t _message_JAM_8[];
|
||||
static const uint8_t _message_NAVX5[];
|
||||
static const uint8_t _message_NAVX5_8[];
|
||||
static const uint8_t _message_NMEA[];
|
||||
static const uint8_t _message_1HZ[];
|
||||
static const uint8_t _message_GGL[];
|
||||
static const uint8_t _message_GLL[];
|
||||
static const uint8_t _message_GSA[];
|
||||
static const uint8_t _message_GSV[];
|
||||
static const uint8_t _message_VTG[];
|
||||
static const uint8_t _message_RMC[];
|
||||
static const uint8_t _message_AID[];
|
||||
static const uint8_t _message_GGA[];
|
||||
static const uint8_t _message_PMS[];
|
||||
static const uint8_t _message_SAVE[];
|
||||
@@ -132,6 +137,9 @@ class GPS : private concurrency::OSThread
|
||||
// Disable the thread
|
||||
int32_t disable() override;
|
||||
|
||||
// toggle between enabled/disabled
|
||||
void toggleGpsMode();
|
||||
|
||||
void setGPSPower(bool on, bool standbyOnly, uint32_t sleepTime);
|
||||
|
||||
/// Returns true if we have acquired GPS lock.
|
||||
@@ -143,7 +151,7 @@ class GPS : private concurrency::OSThread
|
||||
/// Return true if we are connected to a GPS
|
||||
bool isConnected() const { return hasGPS; }
|
||||
|
||||
bool isPowerSaving() const { return !config.position.gps_enabled; }
|
||||
bool isPowerSaving() const { return config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED; }
|
||||
|
||||
// Empty the input buffer as quickly as possible
|
||||
void clearBuffer();
|
||||
|
||||
+196
-88
@@ -2,7 +2,15 @@ uint8_t GPS::_message_PMREQ[] PROGMEM = {
|
||||
0x00, 0x00, // 4 bytes duration of request task
|
||||
0x00, 0x00, // (milliseconds)
|
||||
0x02, 0x00, // Task flag bitfield
|
||||
0x00, 0x00 // byte index 1 = sleep mode
|
||||
0x00, 0x00, // byte index 1 = sleep mode
|
||||
};
|
||||
|
||||
uint8_t GPS::_message_PMREQ_10[] PROGMEM = {
|
||||
0x00, 0x00, // 4 bytes duration of request task
|
||||
0x00, 0x00, // (milliseconds)
|
||||
0x02, 0x00, // Task flag bitfield
|
||||
0x00, 0x00, // byte index 1 = sleep mode
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // wakeupSources
|
||||
};
|
||||
|
||||
const uint8_t GPS::_message_CFG_RXM_PSM[] PROGMEM = {
|
||||
@@ -10,24 +18,32 @@ const uint8_t GPS::_message_CFG_RXM_PSM[] PROGMEM = {
|
||||
0x01 // Power save mode
|
||||
};
|
||||
|
||||
// only for Neo-6
|
||||
const uint8_t GPS::_message_CFG_RXM_ECO[] PROGMEM = {
|
||||
0x08, // Reserved
|
||||
0x04 // eco mode
|
||||
};
|
||||
|
||||
const uint8_t GPS::_message_CFG_PM2[] PROGMEM = {
|
||||
0x01, 0x06, 0x00, 0x00, // version, Reserved
|
||||
0x0E, 0x81, 0x43, 0x01, // flags
|
||||
0x01, // version
|
||||
0x00, // Reserved 1, set to 0x06 by u-Center
|
||||
0x00, // Reserved 2
|
||||
0x00, // Reserved 1
|
||||
0x00, 0x11, 0x03, 0x00, // flags-> cyclic mode, wait for normal fix ok, do not wake to update RTC, doNotEnterOff,
|
||||
// LimitPeakCurrent
|
||||
0xE8, 0x03, 0x00, 0x00, // update period 1000 ms
|
||||
0x10, 0x27, 0x00, 0x00, // search period 10s
|
||||
0x00, 0x00, 0x00, 0x00, // Grod offset 0
|
||||
0x00, 0x00, 0x00, 0x00, // Grid offset 0
|
||||
0x01, 0x00, // onTime 1 second
|
||||
0x00, 0x00, // min search time 0
|
||||
0x2C, 0x01, // reserved
|
||||
0x00, 0x00, 0x4F, 0xC1, // reserved
|
||||
0x03, 0x00, 0x87, 0x02, // reserved
|
||||
0x00, 0x00, 0xFF, 0x00, // reserved
|
||||
0x01, 0x00, 0xD6, 0x4D // reserved
|
||||
0x00, 0x00, // 0x2C, 0x01, // reserved 4
|
||||
0x00, 0x00, // 0x00, 0x00, // reserved 5
|
||||
0x00, 0x00, 0x00, 0x00, // 0x4F, 0xC1, 0x03, 0x00, // reserved 6
|
||||
0x00, 0x00, 0x00, 0x00, // 0x87, 0x02, 0x00, 0x00, // reserved 7
|
||||
0x00, // 0xFF, // reserved 8
|
||||
0x00, // 0x00, // reserved 9
|
||||
0x00, 0x00, // 0x00, 0x00, // reserved 10
|
||||
0x00, 0x00, 0x00, 0x00 // 0x64, 0x40, 0x01, 0x00 // reserved 11
|
||||
};
|
||||
|
||||
const uint8_t GPS::_message_GNSS_7[] = {
|
||||
@@ -46,123 +62,214 @@ const uint8_t GPS::_message_GNSS_7[] = {
|
||||
// to overwrite a saved state with identical values, no ACK/NAK is received, contrary to
|
||||
// what is specified in the Ublox documentation.
|
||||
// There is also a possibility that the module may be GPS-only.
|
||||
const uint8_t GPS::_message_GNSS[] = {
|
||||
0x00, // msgVer (0 for this version)
|
||||
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
|
||||
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
|
||||
0x03, // numConfigBlocks (number of GNSS systems), most modules support maximum 3 GNSS systems
|
||||
// GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags
|
||||
|
||||
// For M8 GPS, GLONASS, Galileo, SBAS, QZSS
|
||||
const uint8_t GPS::_message_GNSS_8[] = {
|
||||
0x00, // msgVer (0 for this version)
|
||||
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
|
||||
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
|
||||
0x05, // numConfigBlocks (number of GNSS systems)
|
||||
// GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags
|
||||
0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, // GPS
|
||||
0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, // SBAS
|
||||
0x06, 0x08, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x01 // GLONASS
|
||||
0x02, 0x04, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, // Galileo
|
||||
0x05, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, // QZSS
|
||||
0x06, 0x08, 0x0E, 0x00, 0x01, 0x00, 0x01, 0x01 // GLONASS
|
||||
};
|
||||
/*
|
||||
// For M8 GPS, GLONASS, BeiDou, SBAS, QZSS
|
||||
const uint8_t GPS::_message_GNSS_8_B[] = {
|
||||
0x00, // msgVer (0 for this version)
|
||||
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
|
||||
0xff, // numTrkChUse (max number of channels to use, 0xff = max available) read only for protocol >23
|
||||
0x05, // numConfigBlocks (number of GNSS systems)
|
||||
// GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags
|
||||
0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, // GPS
|
||||
0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, // SBAS
|
||||
0x03, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, // BeiDou
|
||||
0x05, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, // QZSS
|
||||
0x06, 0x08, 0x0E, 0x00, 0x01, 0x00, 0x01, 0x01 // GLONASS
|
||||
};
|
||||
*/
|
||||
|
||||
// For M8 we want to enable NMEA version 4.10 messages to allow for Galileo and or BeiDou
|
||||
const uint8_t GPS::_message_NMEA[]{
|
||||
0x00, // filter flags
|
||||
0x41, // NMEA Version
|
||||
0x00, // Max number of SVs to report per TaklerId
|
||||
0x02, // flags
|
||||
0x00, 0x00, 0x00, 0x00, // gnssToFilter
|
||||
0x00, // svNumbering
|
||||
0x00, // mainTalkerId
|
||||
0x00, // gsvTalkerId
|
||||
0x01, // Message version
|
||||
0x00, 0x00, // bdsTalkerId 2 chars 0=default
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved
|
||||
};
|
||||
// Enable jamming/interference monitor
|
||||
|
||||
// For Neo-6, Max-7 and Neo-7
|
||||
const uint8_t GPS::_message_JAM_6_7[] = {
|
||||
0xf3, 0xac, 0x62, 0xad, // config1 bbThreshold = 3, cwThreshold = 15, enable = 1, reserved bits 0x16B156
|
||||
0x1e, 0x03, 0x00, 0x00 // config2 antennaSetting Unknown = 0, reserved 3, = 0x00,0x00, reserved 2 = 0x31E
|
||||
};
|
||||
|
||||
// Enable interference resistance, because we are using LoRa, WiFi and Bluetooth on same board,
|
||||
// and we need to reduce interference from them
|
||||
const uint8_t GPS::_message_JAM[] = {
|
||||
// bbThreshold (Broadband jamming detection threshold) is set to 0x3F (63 in decimal)
|
||||
// cwThreshold (CW jamming detection threshold) is set to 0x10 (16 in decimal)
|
||||
// algorithmBits (Reserved algorithm settings) is set to 0x16B156 as recommended
|
||||
// enable (Enable interference detection) is set to 1 (enabled)
|
||||
0x3F, 0x10, 0xB1, 0x56, // config: Interference config word
|
||||
// generalBits (General settings) is set to 0x31E as recommended
|
||||
// antSetting (Antenna setting, 0=unknown, 1=passive, 2=active) is set to 0 (unknown)
|
||||
// ToDo: Set to 1 (passive) or 2 (active) if known, for example from UBX-MON-HW, or from board info
|
||||
// enable2 (Set to 1 to scan auxiliary bands, u-blox 8 / u-blox M8 only, otherwise ignored) is set to 1
|
||||
// (enabled)
|
||||
0x1E, 0x03, 0x00, 0x01 // config2: Extra settings for jamming/interference monitor
|
||||
// For M8
|
||||
const uint8_t GPS::_message_JAM_8[] = {
|
||||
0xf3, 0xac, 0x62, 0xad, // config1 bbThreshold = 3, cwThreshold = 15, enable1 = 1, reserved bits 0x16B156
|
||||
0x1e, 0x43, 0x00, 0x00 // config2 antennaSetting Unknown = 0, enable2 = 1, generalBits = 0x31E
|
||||
};
|
||||
|
||||
// Configure navigation engine expert settings:
|
||||
// there are many variations of what were Reserved fields for the Neo-6 in later versions
|
||||
// ToDo: check UBX-MON-VER for module type and protocol version
|
||||
|
||||
// For the Neo-6
|
||||
const uint8_t GPS::_message_NAVX5[] = {
|
||||
0x00, 0x00, // msgVer (0 for this version)
|
||||
// minMax flag = 1: apply min/max SVs settings
|
||||
// minCno flag = 1: apply minimum C/N0 setting
|
||||
// initial3dfix flag = 0: apply initial 3D fix settings
|
||||
// aop flag = 1: apply aopCfg (useAOP flag) settings (AssistNow Autonomous)
|
||||
0x1B, 0x00, // mask1 (First parameters bitmask)
|
||||
// adr flag = 0: apply ADR sensor fusion on/off setting (useAdr flag)
|
||||
// If firmware is not ADR/UDR, enabling this flag will fail configuration
|
||||
// ToDo: check this with UBX-MON-VER
|
||||
0x00, 0x00, 0x00, 0x00, // mask2 (Second parameters bitmask)
|
||||
0x00, 0x00, // Reserved
|
||||
0x03, // minSVs (Minimum number of satellites for navigation) = 3
|
||||
0x10, // maxSVs (Maximum number of satellites for navigation) = 16
|
||||
0x06, // minCNO (Minimum satellite signal level for navigation) = 6 dBHz
|
||||
0x00, // Reserved
|
||||
0x00, // iniFix3D (Initial fix must be 3D) = 0 (disabled)
|
||||
0x00, 0x00, // Reserved
|
||||
0x00, // ackAiding (Issue acknowledgements for assistance message input) = 0 (disabled)
|
||||
0x00, 0x00, // Reserved
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved
|
||||
0x00, // Reserved
|
||||
0x01, // aopCfg (AssistNow Autonomous configuration) = 1 (enabled)
|
||||
0x00, 0x00, // Reserved
|
||||
0x00, 0x00, // Reserved
|
||||
0x00, 0x00, 0x00, 0x00, // Reserved
|
||||
0x00, 0x00, 0x00, // Reserved
|
||||
0x01, // useAdr (Enable/disable ADR sensor fusion) = 1 (enabled)
|
||||
0x00, 0x00, // msgVer (0 for this version)
|
||||
0x4c, 0x66, // mask1
|
||||
0x00, 0x00, 0x00, 0x00, // Reserved 0
|
||||
0x00, // Reserved 1
|
||||
0x00, // Reserved 2
|
||||
0x03, // minSVs (Minimum number of satellites for navigation) = 3
|
||||
0x10, // maxSVs (Maximum number of satellites for navigation) = 16
|
||||
0x06, // minCNO (Minimum satellite signal level for navigation) = 6 dBHz
|
||||
0x00, // Reserved 5
|
||||
0x00, // iniFix3D (Initial fix must be 3D) (0 = false 1 = true)
|
||||
0x00, // Reserved 6
|
||||
0x00, // Reserved 7
|
||||
0x00, // Reserved 8
|
||||
0x00, 0x00, // wknRollover 0 = firmware default
|
||||
0x00, 0x00, 0x00, 0x00, // Reserved 9
|
||||
0x00, // Reserved 10
|
||||
0x00, // Reserved 11
|
||||
0x00, // usePPP (Precice Point Positioning) (0 = false, 1 = true)
|
||||
0x01, // useAOP (AssistNow Autonomous configuration) = 1 (enabled)
|
||||
0x00, // Reserved 12
|
||||
0x00, // Reserved 13
|
||||
0x00, 0x00, // aopOrbMaxErr = 0 to reset to firmware default
|
||||
0x00, // Reserved 14
|
||||
0x00, // Reserved 15
|
||||
0x00, 0x00, // Reserved 3
|
||||
0x00, 0x00, 0x00, 0x00 // Reserved 4
|
||||
};
|
||||
// For the M8
|
||||
const uint8_t GPS::_message_NAVX5_8[] = {
|
||||
0x02, 0x00, // msgVer (2 for this version)
|
||||
0x4c, 0x66, // mask1
|
||||
0x00, 0x00, 0x00, 0x00, // mask2
|
||||
0x00, 0x00, // Reserved 1
|
||||
0x03, // minSVs (Minimum number of satellites for navigation) = 3
|
||||
0x10, // maxSVs (Maximum number of satellites for navigation) = 16
|
||||
0x06, // minCNO (Minimum satellite signal level for navigation) = 6 dBHz
|
||||
0x00, // Reserved 2
|
||||
0x00, // iniFix3D (Initial fix must be 3D) (0 = false 1 = true)
|
||||
0x00, 0x00, // Reserved 3
|
||||
0x00, // ackAiding
|
||||
0x00, 0x00, // wknRollover 0 = firmware default
|
||||
0x00, // sigAttenCompMode
|
||||
0x00, // Reserved 4
|
||||
0x00, 0x00, // Reserved 5
|
||||
0x00, 0x00, // Reserved 6
|
||||
0x00, // usePPP (Precice Point Positioning) (0 = false, 1 = true)
|
||||
0x01, // aopCfg (AssistNow Autonomous configuration) = 1 (enabled)
|
||||
0x00, 0x00, // Reserved 7
|
||||
0x00, 0x00, // aopOrbMaxErr = 0 to reset to firmware default
|
||||
0x00, 0x00, 0x00, 0x00, // Reserved 8
|
||||
0x00, 0x00, 0x00, // Reserved 9
|
||||
0x00 // useAdr
|
||||
};
|
||||
|
||||
// Set GPS update rate to 1Hz
|
||||
// Lowering the update rate helps to save power.
|
||||
// Additionally, for some new modules like the M9/M10, an update rate lower than 5Hz
|
||||
// is recommended to avoid a known issue with satellites disappearing.
|
||||
// The module defaults for M8, M9, M10 are the same as we use here so no update is necessary
|
||||
const uint8_t GPS::_message_1HZ[] = {
|
||||
0xE8, 0x03, // Measurement Rate (1000ms for 1Hz)
|
||||
0x01, 0x00, // Navigation rate, always 1 in GPS mode
|
||||
0x01, 0x00, // Time reference
|
||||
0x01, 0x00 // Time reference
|
||||
};
|
||||
|
||||
// Disable GGL. GGL - Geographic position (latitude and longitude), which provides the current geographical
|
||||
// Disable GLL. GLL - Geographic position (latitude and longitude), which provides the current geographical
|
||||
// coordinates.
|
||||
const uint8_t GPS::_message_GGL[] = {
|
||||
0xF0, 0x01, // NMEA ID for GLL
|
||||
0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI
|
||||
0x00, // Disable
|
||||
0x01, 0x01, 0x01, 0x01 // Reserved
|
||||
const uint8_t GPS::_message_GLL[] = {
|
||||
0xF0, 0x01, // NMEA ID for GLL
|
||||
0x00, // Rate for DDC
|
||||
0x00, // Rate for UART1
|
||||
0x00, // Rate for UART2
|
||||
0x00, // Rate for USB
|
||||
0x00, // Rate for SPI
|
||||
0x00 // Reserved
|
||||
};
|
||||
|
||||
// Enable GSA. GSA - GPS DOP and active satellites, used for detailing the satellites used in the positioning and
|
||||
// the DOP (Dilution of Precision)
|
||||
const uint8_t GPS::_message_GSA[] = {
|
||||
0xF0, 0x02, // NMEA ID for GSA
|
||||
0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI
|
||||
0x01, // Enable
|
||||
0x01, 0x01, 0x01, 0x01 // Reserved
|
||||
0xF0, 0x02, // NMEA ID for GSA
|
||||
0x00, // Rate for DDC
|
||||
0x01, // Rate for UART1
|
||||
0x00, // Rate for UART2
|
||||
0x00, // Rate for USB
|
||||
0x00, // Rate for SPI
|
||||
0x00 // Reserved
|
||||
};
|
||||
|
||||
// Disable GSV. GSV - Satellites in view, details the number and location of satellites in view.
|
||||
const uint8_t GPS::_message_GSV[] = {
|
||||
0xF0, 0x03, // NMEA ID for GSV
|
||||
0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI
|
||||
0x00, // Disable
|
||||
0x01, 0x01, 0x01, 0x01 // Reserved
|
||||
0xF0, 0x03, // NMEA ID for GSV
|
||||
0x00, // Rate for DDC
|
||||
0x00, // Rate for UART1
|
||||
0x00, // Rate for UART2
|
||||
0x00, // Rate for USB
|
||||
0x00, // Rate for SPI
|
||||
0x00 // Reserved
|
||||
};
|
||||
|
||||
// Disable VTG. VTG - Track made good and ground speed, which provides course and speed information relative to
|
||||
// the ground.
|
||||
const uint8_t GPS::_message_VTG[] = {
|
||||
0xF0, 0x05, // NMEA ID for VTG
|
||||
0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI
|
||||
0x00, // Disable
|
||||
0x01, 0x01, 0x01, 0x01 // Reserved
|
||||
0xF0, 0x05, // NMEA ID for VTG
|
||||
0x00, // Rate for DDC
|
||||
0x00, // Rate for UART1
|
||||
0x00, // Rate for UART2
|
||||
0x00, // Rate for USB
|
||||
0x00, // Rate for SPI
|
||||
0x00 // Reserved
|
||||
};
|
||||
|
||||
// Enable RMC. RMC - Recommended Minimum data, the essential gps pvt (position, velocity, time) data.
|
||||
const uint8_t GPS::_message_RMC[] = {
|
||||
0xF0, 0x04, // NMEA ID for RMC
|
||||
0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI
|
||||
0x01, // Enable
|
||||
0x01, 0x01, 0x01, 0x01 // Reserved
|
||||
0xF0, 0x04, // NMEA ID for RMC
|
||||
0x00, // Rate for DDC
|
||||
0x01, // Rate for UART1
|
||||
0x00, // Rate for UART2
|
||||
0x00, // Rate for USB
|
||||
0x00, // Rate for SPI
|
||||
0x00 // Reserved
|
||||
};
|
||||
|
||||
// Enable GGA. GGA - Global Positioning System Fix Data, which provides 3D location and accuracy data.
|
||||
const uint8_t GPS::_message_GGA[] = {
|
||||
0xF0, 0x00, // NMEA ID for GGA
|
||||
0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI
|
||||
0x01, // Enable
|
||||
0x01, 0x01, 0x01, 0x01 // Reserved
|
||||
0xF0, 0x00, // NMEA ID for GGA
|
||||
0x00, // Rate for DDC
|
||||
0x01, // Rate for UART1
|
||||
0x00, // Rate for UART2
|
||||
0x00, // Rate for USB
|
||||
0x00, // Rate for SPI
|
||||
0x00 // Reserved
|
||||
};
|
||||
|
||||
// Disable UBX-AID-ALPSRV as it may confuse TinyGPS. The Neo-6 seems to send this message
|
||||
// whether the AID Autonomous is enabled or not
|
||||
const uint8_t GPS::_message_AID[] = {
|
||||
0x0B, 0x32, // NMEA ID for UBX-AID-ALPSRV
|
||||
0x00, // Rate for DDC
|
||||
0x00, // Rate for UART1
|
||||
0x00, // Rate for UART2
|
||||
0x00, // Rate for USB
|
||||
0x00, // Rate for SPI
|
||||
0x00 // Reserved
|
||||
};
|
||||
|
||||
// The Power Management configuration allows the GPS module to operate in different power modes for optimized
|
||||
@@ -176,17 +283,18 @@ const uint8_t GPS::_message_GGA[] = {
|
||||
// is set to Interval; otherwise, it must be set to '0'. The 'onTime' field specifies the duration of the ON phase
|
||||
// and must be smaller than the period. It is only valid when the powerSetupValue is set to Interval; otherwise,
|
||||
// it must be set to '0'.
|
||||
// This command applies to M8 and higher products
|
||||
const uint8_t GPS::_message_PMS[] = {
|
||||
0x00, // Version (0)
|
||||
0x03, // Power setup value
|
||||
0x03, // Power setup value 3 = Agresssive 1Hz
|
||||
0x00, 0x00, // period: not applicable, set to 0
|
||||
0x00, 0x00, // onTime: not applicable, set to 0
|
||||
0x97, 0x6F // reserved, generated by u-center
|
||||
0x00, 0x00 // reserved, generated by u-center
|
||||
};
|
||||
|
||||
const uint8_t GPS::_message_SAVE[] = {
|
||||
0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared
|
||||
0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections
|
||||
0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded
|
||||
0x0F // deviceMask: BBR, Flash, EEPROM, and SPI Flash
|
||||
};
|
||||
0x17 // deviceMask: BBR, Flash, EEPROM, and SPI Flash
|
||||
};
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "main.h"
|
||||
#include <SPI.h>
|
||||
|
||||
#ifdef HELTEC_WIRELESS_PAPER
|
||||
#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0)
|
||||
SPIClass *hspi = NULL;
|
||||
#endif
|
||||
|
||||
@@ -48,6 +48,11 @@ SPIClass *hspi = NULL;
|
||||
#elif defined(HELTEC_WIRELESS_PAPER)
|
||||
// #define TECHO_DISPLAY_MODEL GxEPD2_213_T5D
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_213_FC1
|
||||
|
||||
#elif defined(HELTEC_WIRELESS_PAPER_V1_0)
|
||||
// 2.13" 122x250 - DEPG0213BNS800
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_213_BN
|
||||
|
||||
#endif
|
||||
|
||||
GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay;
|
||||
@@ -70,6 +75,17 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY
|
||||
// GxEPD2_154_M09
|
||||
// setGeometry(GEOMETRY_RAWMODE, 200, 200);
|
||||
|
||||
#elif defined(HELTEC_WIRELESS_PAPER_V1_0)
|
||||
|
||||
// The display's memory is actually 128px x 250px
|
||||
// Setting the buffersize manually prevents 122/8 truncating to a 15 byte width
|
||||
// (Or something like that..)
|
||||
|
||||
this->geometry = GEOMETRY_RAWMODE;
|
||||
this->displayWidth = 250;
|
||||
this->displayHeight = 122;
|
||||
this->displayBufferSize = 250 * (128 / 8);
|
||||
|
||||
#elif defined(HELTEC_WIRELESS_PAPER)
|
||||
// GxEPD2_213_BN - 2.13 inch b/w 250x122
|
||||
setGeometry(GEOMETRY_RAWMODE, 250, 122);
|
||||
@@ -146,6 +162,8 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
|
||||
#elif defined(PCA10059) || defined(M5_COREINK)
|
||||
adafruitDisplay->nextPage();
|
||||
#elif defined(HELTEC_WIRELESS_PAPER_V1_0)
|
||||
adafruitDisplay->nextPage();
|
||||
#elif defined(HELTEC_WIRELESS_PAPER)
|
||||
adafruitDisplay->nextPage();
|
||||
#elif defined(PRIVATE_HW) || defined(my)
|
||||
@@ -229,6 +247,43 @@ bool EInkDisplay::connect()
|
||||
(void)adafruitDisplay;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(HELTEC_WIRELESS_PAPER_V1_0)
|
||||
{
|
||||
// Is this a normal boot, or a wake from deep sleep?
|
||||
esp_sleep_wakeup_cause_t wakeReason = esp_sleep_get_wakeup_cause();
|
||||
|
||||
// If waking from sleep, need to reverse rtc_gpio_isolate(), called in cpuDeepSleep()
|
||||
// Otherwise, SPI won't work
|
||||
if (wakeReason != ESP_SLEEP_WAKEUP_UNDEFINED) {
|
||||
// HSPI + other display pins
|
||||
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_SCLK);
|
||||
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_DC);
|
||||
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_RES);
|
||||
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_BUSY);
|
||||
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_CS);
|
||||
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_MOSI);
|
||||
}
|
||||
|
||||
// Start HSPI
|
||||
hspi = new SPIClass(HSPI);
|
||||
hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS
|
||||
|
||||
// Enable VExt (ACTIVE LOW)
|
||||
// Unsure if called elsewhere first?
|
||||
delay(100);
|
||||
pinMode(Vext, OUTPUT);
|
||||
digitalWrite(Vext, LOW);
|
||||
delay(100);
|
||||
|
||||
// Create GxEPD2 objects
|
||||
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *hspi);
|
||||
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
||||
|
||||
// Init GxEPD2
|
||||
adafruitDisplay->init();
|
||||
adafruitDisplay->setRotation(3);
|
||||
}
|
||||
#elif defined(HELTEC_WIRELESS_PAPER)
|
||||
{
|
||||
hspi = new SPIClass(HSPI);
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
#include <OLEDDisplay.h>
|
||||
|
||||
#if defined(HELTEC_WIRELESS_PAPER_V1_0)
|
||||
// Re-enable SPI after deep sleep: rtc_gpio_hold_dis()
|
||||
#include "driver/rtc_io.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* An adapter class that allows using the GxEPD2 library as if it was an OLEDDisplay implementation.
|
||||
*
|
||||
|
||||
+16
-14
@@ -150,7 +150,7 @@ static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDispl
|
||||
|
||||
// draw centered icon left to right and centered above the one line of app text
|
||||
display->drawXbm(x + (SCREEN_WIDTH - icon_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - icon_height) / 2 + 2,
|
||||
icon_width, icon_height, (const uint8_t *)icon_bits);
|
||||
icon_width, icon_height, icon_bits);
|
||||
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
@@ -558,15 +558,20 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
|
||||
}
|
||||
}
|
||||
|
||||
// Draw status when gps is disabled by PMU
|
||||
// Draw status when GPS is disabled or not present
|
||||
static void drawGPSpowerstat(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
|
||||
{
|
||||
String displayLine = "GPS disabled";
|
||||
int16_t xPos = display->getStringWidth(displayLine);
|
||||
|
||||
if (!config.position.gps_enabled) {
|
||||
display->drawString(x + xPos, y, displayLine);
|
||||
String displayLine;
|
||||
int pos;
|
||||
if (y < FONT_HEIGHT_SMALL) { // Line 1: use short string
|
||||
displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off";
|
||||
pos = SCREEN_WIDTH - display->getStringWidth(displayLine);
|
||||
} else {
|
||||
displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "GPS not present"
|
||||
: "GPS is disabled";
|
||||
pos = (SCREEN_WIDTH - display->getStringWidth(displayLine)) / 2;
|
||||
}
|
||||
display->drawString(x + pos, y, displayLine);
|
||||
}
|
||||
|
||||
static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
|
||||
@@ -594,7 +599,7 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
|
||||
String displayLine = "";
|
||||
|
||||
if (!gps->getIsConnected() && !config.position.fixed_position) {
|
||||
displayLine = "No GPS Module";
|
||||
displayLine = "No GPS present";
|
||||
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
|
||||
} else if (!gps->getHasLock() && !config.position.fixed_position) {
|
||||
displayLine = "No GPS Lock";
|
||||
@@ -1549,7 +1554,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 3, nodeStatus);
|
||||
}
|
||||
// Display GPS status
|
||||
if (!config.position.gps_enabled) {
|
||||
if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
||||
drawGPSpowerstat(display, x, y + 2, gpsStatus);
|
||||
} else {
|
||||
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
|
||||
@@ -1777,7 +1782,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
char chUtil[13];
|
||||
snprintf(chUtil, sizeof(chUtil), "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), y + FONT_HEIGHT_SMALL * 1, chUtil);
|
||||
if (config.position.gps_enabled) {
|
||||
if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
||||
// Line 3
|
||||
if (config.display.gps_format !=
|
||||
meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DMS) // if DMS then don't draw altitude
|
||||
@@ -1786,10 +1791,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
// Line 4
|
||||
drawGPScoordinates(display, x, y + FONT_HEIGHT_SMALL * 3, gpsStatus);
|
||||
} else {
|
||||
drawGPSpowerstat(display, x - (SCREEN_WIDTH / 4), y + FONT_HEIGHT_SMALL * 2, gpsStatus);
|
||||
#ifdef GPS_POWER_TOGGLE
|
||||
display->drawString(x + 30, (y + FONT_HEIGHT_SMALL * 3), " by button");
|
||||
#endif
|
||||
drawGPSpowerstat(display, x, y + FONT_HEIGHT_SMALL * 2, gpsStatus);
|
||||
}
|
||||
/* Display a heartbeat pixel that blinks every time the frame is redrawn */
|
||||
#ifdef SHOW_REDRAWS
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
#define TFT_BL ST7735_BACKLIGHT_EN
|
||||
#endif
|
||||
|
||||
#ifndef TFT_INVERT
|
||||
#define TFT_INVERT true
|
||||
#endif
|
||||
|
||||
class LGFX : public lgfx::LGFX_Device
|
||||
{
|
||||
lgfx::Panel_ST7735S _panel_instance;
|
||||
@@ -68,7 +72,7 @@ class LGFX : public lgfx::LGFX_Device
|
||||
cfg.dummy_read_pixel = 8; // Number of bits for dummy read before pixel readout
|
||||
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
|
||||
cfg.readable = true; // Set to true if data can be read
|
||||
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed
|
||||
cfg.invert = TFT_INVERT; // Set to true if the light/darkness of the panel is reversed
|
||||
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
|
||||
cfg.dlen_16bit =
|
||||
false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
|
||||
@@ -350,6 +354,8 @@ class LGFX : public lgfx::LGFX_Device
|
||||
_panel_instance = new lgfx::Panel_ST7735;
|
||||
else if (settingsMap[displayPanel] == st7735s)
|
||||
_panel_instance = new lgfx::Panel_ST7735S;
|
||||
else if (settingsMap[displayPanel] == ili9341)
|
||||
_panel_instance = new lgfx::Panel_ILI9341;
|
||||
auto buscfg = _bus_instance.config();
|
||||
buscfg.spi_mode = 0;
|
||||
|
||||
@@ -375,6 +381,8 @@ class LGFX : public lgfx::LGFX_Device
|
||||
if (settingsMap[touchscreenModule]) {
|
||||
if (settingsMap[touchscreenModule] == xpt2046) {
|
||||
_touch_instance = new lgfx::Touch_XPT2046;
|
||||
} else if (settingsMap[touchscreenModule] == stmpe610) {
|
||||
_touch_instance = new lgfx::Touch_STMPE610;
|
||||
}
|
||||
auto touch_cfg = _touch_instance->config();
|
||||
|
||||
@@ -598,7 +606,7 @@ bool TFTDisplay::connect()
|
||||
tft->setRotation(1);
|
||||
tft->setSwapBytes(true);
|
||||
// tft->fillScreen(TFT_BLACK);
|
||||
#elif defined(T_DECK) || defined(PICOMPUTER_S3)
|
||||
#elif defined(T_DECK) || defined(PICOMPUTER_S3) || defined(CHATTER_2)
|
||||
tft->setRotation(1); // T-Deck has the TFT in landscape
|
||||
#elif defined(T_WATCH_S3)
|
||||
tft->setRotation(2); // T-Watch S3 left-handed orientation
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#define icon_width 50
|
||||
#define icon_height 28
|
||||
static char icon_bits[] = {
|
||||
static uint8_t icon_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x03,
|
||||
0x00, 0x00, 0x00, 0x80, 0x07, 0xC0, 0x07, 0x00, 0x00, 0x00, 0xC0, 0x1F,
|
||||
0xC0, 0x0F, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0x00, 0x00, 0x00,
|
||||
@@ -17,4 +17,4 @@ static char icon_bits[] = {
|
||||
0xFE, 0x00, 0x00, 0xFC, 0x01, 0x7E, 0x00, 0x7F, 0x00, 0x00, 0xF8, 0x01,
|
||||
0x7E, 0x00, 0x3E, 0x00, 0x00, 0xF8, 0x01, 0x38, 0x00, 0x3C, 0x00, 0x00,
|
||||
0x70, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, };
|
||||
0x00, 0x00, 0x00, 0x00, };
|
||||
+24
-2
@@ -248,6 +248,11 @@ void setup()
|
||||
digitalWrite(PIN_EINK_PWR_ON, HIGH);
|
||||
#endif
|
||||
|
||||
#if defined(LORA_TCXO_GPIO)
|
||||
pinMode(LORA_TCXO_GPIO, OUTPUT);
|
||||
digitalWrite(LORA_TCXO_GPIO, HIGH);
|
||||
#endif
|
||||
|
||||
#ifdef ST7735_BL_V03 // Heltec Wireless Tracker PCB Change Detect/Hack
|
||||
|
||||
rtc_clk_32k_enable(true);
|
||||
@@ -363,6 +368,13 @@ void setup()
|
||||
Wire.begin();
|
||||
#elif defined(I2C_SDA) && !defined(ARCH_RP2040)
|
||||
Wire.begin(I2C_SDA, I2C_SCL);
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
if (settingsStrings[i2cdev] != "") {
|
||||
LOG_INFO("Using %s as I2C device.\n", settingsStrings[i2cdev]);
|
||||
Wire.begin(settingsStrings[i2cdev].c_str());
|
||||
} else {
|
||||
LOG_INFO("No I2C device configured, skipping.\n");
|
||||
}
|
||||
#elif HAS_WIRE
|
||||
Wire.begin();
|
||||
#endif
|
||||
@@ -408,8 +420,9 @@ void setup()
|
||||
// We need to scan here to decide if we have a screen for nodeDB.init() and because power has been applied to
|
||||
// accessories
|
||||
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
|
||||
|
||||
#ifdef HAS_WIRE
|
||||
LOG_INFO("Scanning for i2c devices...\n");
|
||||
#endif
|
||||
|
||||
#if defined(I2C_SDA1) && defined(ARCH_RP2040)
|
||||
Wire1.setSDA(I2C_SDA1);
|
||||
@@ -429,6 +442,11 @@ void setup()
|
||||
#elif defined(I2C_SDA) && !defined(ARCH_RP2040)
|
||||
Wire.begin(I2C_SDA, I2C_SCL);
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
if (settingsStrings[i2cdev] != "") {
|
||||
LOG_INFO("Scanning for i2c devices...\n");
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
|
||||
}
|
||||
#elif HAS_WIRE
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
|
||||
#endif
|
||||
@@ -667,7 +685,8 @@ void setup()
|
||||
readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time)
|
||||
|
||||
// If we're taking on the repeater role, ignore GPS
|
||||
if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||
if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
|
||||
config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) {
|
||||
gps = GPS::createGps();
|
||||
}
|
||||
if (gps) {
|
||||
@@ -717,6 +736,7 @@ void setup()
|
||||
#ifdef ARCH_PORTDUINO
|
||||
if (settingsMap[use_sx1262]) {
|
||||
if (!rIf) {
|
||||
LOG_DEBUG("Attempting to activate sx1262 radio on SPI port %s\n", settingsStrings[spidev].c_str());
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new SX1262Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
@@ -730,6 +750,7 @@ void setup()
|
||||
}
|
||||
} else if (settingsMap[use_rf95]) {
|
||||
if (!rIf) {
|
||||
LOG_DEBUG("Attempting to activate rf95 radio on SPI port %s\n", settingsStrings[spidev].c_str());
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new RF95Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
@@ -744,6 +765,7 @@ void setup()
|
||||
}
|
||||
} else if (settingsMap[use_sx1280]) {
|
||||
if (!rIf) {
|
||||
LOG_DEBUG("Attempting to activate sx1280 radio on SPI port %s\n", settingsStrings[spidev].c_str());
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
rIf = new SX1280Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
|
||||
settingsMap[busy]);
|
||||
|
||||
@@ -15,6 +15,7 @@ Channels channels;
|
||||
const char *Channels::adminChannel = "admin";
|
||||
const char *Channels::gpioChannel = "gpio";
|
||||
const char *Channels::serialChannel = "serial";
|
||||
const char *Channels::mqttChannel = "mqtt";
|
||||
|
||||
uint8_t xorHash(const uint8_t *p, size_t len)
|
||||
{
|
||||
@@ -313,4 +314,4 @@ bool Channels::decryptForHash(ChannelIndex chIndex, ChannelHash channelHash)
|
||||
int16_t Channels::setActiveByIndex(ChannelIndex channelIndex)
|
||||
{
|
||||
return setCrypto(channelIndex);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -32,7 +32,7 @@ class Channels
|
||||
Channels() {}
|
||||
|
||||
/// Well known channel names
|
||||
static const char *adminChannel, *gpioChannel, *serialChannel;
|
||||
static const char *adminChannel, *gpioChannel, *serialChannel, *mqttChannel;
|
||||
|
||||
const meshtastic_ChannelSettings &getPrimary() { return getByIndex(getPrimaryIndex()).settings; }
|
||||
|
||||
@@ -139,4 +139,4 @@ class Channels
|
||||
};
|
||||
|
||||
/// Singleton channel table
|
||||
extern Channels channels;
|
||||
extern Channels channels;
|
||||
@@ -67,7 +67,7 @@ meshtastic_MeshPacket *MeshModule::allocErrorResponse(meshtastic_Routing_Error e
|
||||
return r;
|
||||
}
|
||||
|
||||
void MeshModule::callPlugins(const meshtastic_MeshPacket &mp, RxSource src)
|
||||
void MeshModule::callPlugins(meshtastic_MeshPacket &mp, RxSource src)
|
||||
{
|
||||
// LOG_DEBUG("In call modules\n");
|
||||
bool moduleFound = false;
|
||||
@@ -124,9 +124,10 @@ void MeshModule::callPlugins(const meshtastic_MeshPacket &mp, RxSource src)
|
||||
} else
|
||||
printPacket("packet on wrong channel, but can't respond", &mp);
|
||||
} else {
|
||||
|
||||
ProcessMessage handled = pi.handleReceived(mp);
|
||||
|
||||
pi.alterReceived(mp);
|
||||
|
||||
// Possibly send replies (but only if the message was directed to us specifically, i.e. not for promiscious
|
||||
// sniffing) also: we only let the one module send a reply, once that happens, remaining modules are not
|
||||
// considered
|
||||
|
||||
+10
-17
@@ -64,7 +64,7 @@ class MeshModule
|
||||
|
||||
/** For use only by MeshService
|
||||
*/
|
||||
static void callPlugins(const meshtastic_MeshPacket &mp, RxSource src = RX_SRC_RADIO);
|
||||
static void callPlugins(meshtastic_MeshPacket &mp, RxSource src = RX_SRC_RADIO);
|
||||
|
||||
static std::vector<MeshModule *> GetMeshModulesWithUIFrames();
|
||||
static void observeUIEvents(Observer<const UIFrameEvent *> *observer);
|
||||
@@ -72,10 +72,7 @@ class MeshModule
|
||||
meshtastic_AdminMessage *request,
|
||||
meshtastic_AdminMessage *response);
|
||||
#if HAS_SCREEN
|
||||
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
return;
|
||||
}
|
||||
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { return; }
|
||||
#endif
|
||||
protected:
|
||||
const char *name;
|
||||
@@ -135,10 +132,12 @@ class MeshModule
|
||||
@return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for
|
||||
it
|
||||
*/
|
||||
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
return ProcessMessage::CONTINUE;
|
||||
}
|
||||
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) { return ProcessMessage::CONTINUE; }
|
||||
|
||||
/** Called to change a particular incoming message
|
||||
This allows the module to change the message before it is passed through the rest of the call-chain.
|
||||
*/
|
||||
virtual void alterReceived(meshtastic_MeshPacket &mp) {}
|
||||
|
||||
/** Messages can be received that have the want_response bit set. If set, this callback will be invoked
|
||||
* so that subclasses can (optionally) send a response back to the original sender.
|
||||
@@ -151,14 +150,8 @@ class MeshModule
|
||||
/***
|
||||
* @return true if you want to be alloced a UI screen frame
|
||||
*/
|
||||
virtual bool wantUIFrame()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual Observable<const UIFrameEvent *> *getUIFrameObservable()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
virtual bool wantUIFrame() { return false; }
|
||||
virtual Observable<const UIFrameEvent *> *getUIFrameObservable() { return NULL; }
|
||||
|
||||
meshtastic_MeshPacket *allocAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex);
|
||||
|
||||
|
||||
@@ -108,8 +108,9 @@ void MeshService::loop()
|
||||
(void)sendQueueStatusToPhone(qs, 0, 0);
|
||||
}
|
||||
if (oldFromNum != fromNum) { // We don't want to generate extra notifies for multiple new packets
|
||||
fromNumChanged.notifyObservers(fromNum);
|
||||
oldFromNum = fromNum;
|
||||
int result = fromNumChanged.notifyObservers(fromNum);
|
||||
if (result == 0) // If any observer returns non-zero, we will try again
|
||||
oldFromNum = fromNum;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-3
@@ -182,7 +182,16 @@ void NodeDB::installDefaultConfig()
|
||||
#else
|
||||
config.device.disable_triple_click = true;
|
||||
#endif
|
||||
config.position.gps_enabled = true;
|
||||
#if !HAS_GPS || defined(T_DECK)
|
||||
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT;
|
||||
#elif !defined(GPS_RX_PIN)
|
||||
if (config.position.rx_gpio == 0)
|
||||
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT;
|
||||
else
|
||||
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_DISABLED;
|
||||
#else
|
||||
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED;
|
||||
#endif
|
||||
config.position.position_broadcast_smart_enabled = true;
|
||||
config.position.broadcast_smart_minimum_distance = 100;
|
||||
config.position.broadcast_smart_minimum_interval_secs = 30;
|
||||
@@ -454,6 +463,11 @@ void NodeDB::init()
|
||||
memcpy(devicestate.node_remote_hardware_pins, empty, sizeof(empty));
|
||||
}
|
||||
|
||||
if (config.position.gps_enabled) {
|
||||
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED;
|
||||
config.position.gps_enabled = 0;
|
||||
}
|
||||
|
||||
saveToDisk(saveWhat);
|
||||
}
|
||||
|
||||
@@ -879,10 +893,11 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
|
||||
if ((*numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfoLite_size * 3)) {
|
||||
if (screen)
|
||||
screen->print("warning: node_db_lite full! erasing oldest entry\n");
|
||||
LOG_INFO("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++) {
|
||||
for (int i = 1; i < *numMeshNodes; i++) {
|
||||
if (meshNodes[i].last_heard < oldest) {
|
||||
oldest = meshNodes[i].last_heard;
|
||||
oldestIndex = i;
|
||||
@@ -926,4 +941,4 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co
|
||||
LOG_ERROR("A critical failure occurred, portduino is exiting...");
|
||||
exit(2);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -62,15 +62,17 @@ void PhoneAPI::close()
|
||||
}
|
||||
}
|
||||
|
||||
void PhoneAPI::checkConnectionTimeout()
|
||||
bool PhoneAPI::checkConnectionTimeout()
|
||||
{
|
||||
if (isConnected()) {
|
||||
bool newContact = checkIsConnected();
|
||||
if (!newContact) {
|
||||
LOG_INFO("Lost phone connection\n");
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -461,8 +463,8 @@ bool PhoneAPI::handleToRadioPacket(meshtastic_MeshPacket &p)
|
||||
/// If the mesh service tells us fromNum has changed, tell the phone
|
||||
int PhoneAPI::onNotify(uint32_t newValue)
|
||||
{
|
||||
checkConnectionTimeout(); // a handy place to check if we've heard from the phone (since the BLE version doesn't call this
|
||||
// from idle)
|
||||
bool timeout = checkConnectionTimeout(); // a handy place to check if we've heard from the phone (since the BLE version
|
||||
// doesn't call this from idle)
|
||||
|
||||
if (state == STATE_SEND_PACKETS) {
|
||||
LOG_INFO("Telling client we have new packets %u\n", newValue);
|
||||
@@ -471,5 +473,5 @@ int PhoneAPI::onNotify(uint32_t newValue)
|
||||
LOG_DEBUG("(Client not yet interested in packets)\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return timeout ? -1 : 0; // If we timed out, MeshService should stop iterating through observers as we just removed one
|
||||
}
|
||||
+3
-3
@@ -108,8 +108,8 @@ class PhoneAPI
|
||||
/// Hookable to find out when connection changes
|
||||
virtual void onConnectionChanged(bool connected) {}
|
||||
|
||||
/// If we haven't heard from the other side in a while then say not connected
|
||||
void checkConnectionTimeout();
|
||||
/// If we haven't heard from the other side in a while then say not connected. Returns true if timeout occurred
|
||||
bool checkConnectionTimeout();
|
||||
|
||||
/// Check the current underlying physical link to see if the client is currently connected
|
||||
virtual bool checkIsConnected() = 0;
|
||||
@@ -142,4 +142,4 @@ class PhoneAPI
|
||||
|
||||
/// If the mesh service tells us fromNum has changed, tell the phone
|
||||
virtual int onNotify(uint32_t newValue) override;
|
||||
};
|
||||
};
|
||||
@@ -30,6 +30,10 @@ template <class T> class ProtobufModule : protected SinglePortModule
|
||||
*/
|
||||
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, T *decoded) = 0;
|
||||
|
||||
/** Called to make changes to a particular incoming message
|
||||
*/
|
||||
virtual void alterReceivedProtobuf(meshtastic_MeshPacket &mp, T *decoded){};
|
||||
|
||||
/**
|
||||
* Return a mesh packet which has been preinited with a particular protobuf data payload and port number.
|
||||
* You can then send this packet (after customizing any of the payload fields you might need) with
|
||||
@@ -86,4 +90,26 @@ template <class T> class ProtobufModule : protected SinglePortModule
|
||||
|
||||
return handleReceivedProtobuf(mp, decoded) ? ProcessMessage::STOP : ProcessMessage::CONTINUE;
|
||||
}
|
||||
|
||||
/** Called to alter a particular incoming message
|
||||
*/
|
||||
virtual void alterReceived(meshtastic_MeshPacket &mp) override
|
||||
{
|
||||
auto &p = mp.decoded;
|
||||
|
||||
T scratch;
|
||||
T *decoded = NULL;
|
||||
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.decoded.portnum == ourPortNum) {
|
||||
memset(&scratch, 0, sizeof(scratch));
|
||||
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, fields, &scratch)) {
|
||||
decoded = &scratch;
|
||||
} else {
|
||||
LOG_ERROR("Error decoding protobuf module!\n");
|
||||
// if we can't decode it, nobody can process it!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return alterReceivedProtobuf(mp, decoded);
|
||||
}
|
||||
};
|
||||
@@ -123,6 +123,13 @@ const RegionInfo regions[] = {
|
||||
*/
|
||||
RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false),
|
||||
|
||||
/*
|
||||
Singapore
|
||||
SG_923 Band 30d: 917 - 925 MHz at 100mW, no restrictions.
|
||||
https://www.imda.gov.sg/-/media/imda/files/regulation-licensing-and-consultations/ict-standards/telecommunication-standards/radio-comms/imdatssrd.pdf
|
||||
*/
|
||||
RDEF(SG_923, 917.0f, 925.0f, 100, 0, 20, true, false, false),
|
||||
|
||||
/*
|
||||
2.4 GHZ WLAN Band equivalent. Only for SX128x chips.
|
||||
*/
|
||||
|
||||
@@ -168,10 +168,14 @@ bool ReliableRouter::stopRetransmission(GlobalPacketId key)
|
||||
auto p = old->packet;
|
||||
auto numErased = pending.erase(key);
|
||||
assert(numErased == 1);
|
||||
// remove the 'original' (identified by originator and packet->id) from the txqueue and free it
|
||||
cancelSending(getFrom(p), p->id);
|
||||
// now free the pooled copy for retransmission too
|
||||
packetPool.release(p);
|
||||
/* Only when we already transmitted a packet via LoRa, we will cancel the packet in the Tx queue
|
||||
to avoid canceling a transmission if it was ACKed super fast via MQTT */
|
||||
if (old->numRetransmissions < NUM_RETRANSMISSIONS - 1) {
|
||||
// remove the 'original' (identified by originator and packet->id) from the txqueue and free it
|
||||
cancelSending(getFrom(p), p->id);
|
||||
// now free the pooled copy for retransmission too
|
||||
packetPool.release(p);
|
||||
}
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
||||
+6
-13
@@ -248,28 +248,21 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
|
||||
// If the packet is not yet encrypted, do so now
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
ChannelIndex chIndex = p->channel; // keep as a local because we are about to change it
|
||||
|
||||
if (moduleConfig.mqtt.enabled) {
|
||||
|
||||
LOG_INFO("Should encrypt MQTT?: %d\n", moduleConfig.mqtt.encryption_enabled);
|
||||
|
||||
// the packet is currently in a decrypted state. send it now if they want decrypted packets
|
||||
if (mqtt && !moduleConfig.mqtt.encryption_enabled)
|
||||
mqtt->onSend(*p, chIndex);
|
||||
}
|
||||
meshtastic_MeshPacket *p_decoded = packetPool.allocCopy(*p);
|
||||
|
||||
auto encodeResult = perhapsEncode(p);
|
||||
if (encodeResult != meshtastic_Routing_Error_NONE) {
|
||||
packetPool.release(p_decoded);
|
||||
abortSendAndNak(encodeResult, p);
|
||||
return encodeResult; // FIXME - this isn't a valid ErrorCode
|
||||
}
|
||||
|
||||
if (moduleConfig.mqtt.enabled) {
|
||||
// the packet is now encrypted.
|
||||
// check if we should send encrypted packets to mqtt
|
||||
if (mqtt && moduleConfig.mqtt.encryption_enabled)
|
||||
mqtt->onSend(*p, chIndex);
|
||||
LOG_INFO("Should encrypt MQTT?: %d\n", moduleConfig.mqtt.encryption_enabled);
|
||||
if (mqtt)
|
||||
mqtt->onSend(*p, *p_decoded, chIndex);
|
||||
}
|
||||
packetPool.release(p_decoded);
|
||||
}
|
||||
|
||||
assert(iface); // This should have been detected already in sendLocal (or we just received a packet from outside)
|
||||
|
||||
@@ -134,6 +134,8 @@ typedef struct _meshtastic_AdminMessage {
|
||||
/* Enter (UF2) DFU mode
|
||||
Only implemented on NRF52 currently */
|
||||
bool enter_dfu_mode_request;
|
||||
/* Delete the file by the specified path from the device */
|
||||
char delete_file_request[201];
|
||||
/* Set the owner for this node */
|
||||
meshtastic_User set_owner;
|
||||
/* Set channels (using the new API).
|
||||
@@ -228,6 +230,7 @@ extern "C" {
|
||||
#define meshtastic_AdminMessage_get_node_remote_hardware_pins_request_tag 19
|
||||
#define meshtastic_AdminMessage_get_node_remote_hardware_pins_response_tag 20
|
||||
#define meshtastic_AdminMessage_enter_dfu_mode_request_tag 21
|
||||
#define meshtastic_AdminMessage_delete_file_request_tag 22
|
||||
#define meshtastic_AdminMessage_set_owner_tag 32
|
||||
#define meshtastic_AdminMessage_set_channel_tag 33
|
||||
#define meshtastic_AdminMessage_set_config_tag 34
|
||||
@@ -266,6 +269,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_ham_mode,set_ham_mode),
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,get_node_remote_hardware_pins_request,get_node_remote_hardware_pins_request), 19) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_node_remote_hardware_pins_response,get_node_remote_hardware_pins_response), 20) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,enter_dfu_mode_request,enter_dfu_mode_request), 21) \
|
||||
X(a, STATIC, ONEOF, STRING, (payload_variant,delete_file_request,delete_file_request), 22) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_owner,set_owner), 32) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_channel,set_channel), 33) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_config,set_config), 34) \
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.7 */
|
||||
|
||||
#include "meshtastic/atak.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(meshtastic_TAKPacket, meshtastic_TAKPacket, 2)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_GeoChat, meshtastic_GeoChat, 2)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_Group, meshtastic_Group, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_Status, meshtastic_Status, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_Contact, meshtastic_Contact, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_PLI, meshtastic_PLI, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,274 @@
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.7 */
|
||||
|
||||
#ifndef PB_MESHTASTIC_MESHTASTIC_ATAK_PB_H_INCLUDED
|
||||
#define PB_MESHTASTIC_MESHTASTIC_ATAK_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _meshtastic_Team {
|
||||
/* Unspecifed */
|
||||
meshtastic_Team_Unspecifed_Color = 0,
|
||||
/* White */
|
||||
meshtastic_Team_White = 1,
|
||||
/* Yellow */
|
||||
meshtastic_Team_Yellow = 2,
|
||||
/* Orange */
|
||||
meshtastic_Team_Orange = 3,
|
||||
/* Magenta */
|
||||
meshtastic_Team_Magenta = 4,
|
||||
/* Red */
|
||||
meshtastic_Team_Red = 5,
|
||||
/* Maroon */
|
||||
meshtastic_Team_Maroon = 6,
|
||||
/* Purple */
|
||||
meshtastic_Team_Purple = 7,
|
||||
/* Dark Blue */
|
||||
meshtastic_Team_Dark_Blue = 8,
|
||||
/* Blue */
|
||||
meshtastic_Team_Blue = 9,
|
||||
/* Cyan */
|
||||
meshtastic_Team_Cyan = 10,
|
||||
/* Teal */
|
||||
meshtastic_Team_Teal = 11,
|
||||
/* Green */
|
||||
meshtastic_Team_Green = 12,
|
||||
/* Dark Green */
|
||||
meshtastic_Team_Dark_Green = 13,
|
||||
/* Brown */
|
||||
meshtastic_Team_Brown = 14
|
||||
} meshtastic_Team;
|
||||
|
||||
/* Role of the group member */
|
||||
typedef enum _meshtastic_MemberRole {
|
||||
/* Unspecifed */
|
||||
meshtastic_MemberRole_Unspecifed = 0,
|
||||
/* Team Member */
|
||||
meshtastic_MemberRole_TeamMember = 1,
|
||||
/* Team Lead */
|
||||
meshtastic_MemberRole_TeamLead = 2,
|
||||
/* Headquarters */
|
||||
meshtastic_MemberRole_HQ = 3,
|
||||
/* Airsoft enthusiast */
|
||||
meshtastic_MemberRole_Sniper = 4,
|
||||
/* Medic */
|
||||
meshtastic_MemberRole_Medic = 5,
|
||||
/* ForwardObserver */
|
||||
meshtastic_MemberRole_ForwardObserver = 6,
|
||||
/* Radio Telephone Operator */
|
||||
meshtastic_MemberRole_RTO = 7,
|
||||
/* Doggo */
|
||||
meshtastic_MemberRole_K9 = 8
|
||||
} meshtastic_MemberRole;
|
||||
|
||||
/* Struct definitions */
|
||||
/* ATAK GeoChat message */
|
||||
typedef struct _meshtastic_GeoChat {
|
||||
/* The text message */
|
||||
char message[200];
|
||||
/* Uid recipient of the message */
|
||||
bool has_to;
|
||||
char to[120];
|
||||
} meshtastic_GeoChat;
|
||||
|
||||
/* ATAK Group
|
||||
<__group role='Team Member' name='Cyan'/> */
|
||||
typedef struct _meshtastic_Group {
|
||||
/* Role of the group member */
|
||||
meshtastic_MemberRole role;
|
||||
/* Team (color)
|
||||
Default Cyan */
|
||||
meshtastic_Team team;
|
||||
} meshtastic_Group;
|
||||
|
||||
/* ATAK EUD Status
|
||||
<status battery='100' /> */
|
||||
typedef struct _meshtastic_Status {
|
||||
/* Battery level */
|
||||
uint8_t battery;
|
||||
} meshtastic_Status;
|
||||
|
||||
/* ATAK Contact
|
||||
<contact endpoint='0.0.0.0:4242:tcp' phone='+12345678' callsign='FALKE'/> */
|
||||
typedef struct _meshtastic_Contact {
|
||||
/* Callsign */
|
||||
char callsign[120];
|
||||
/* Device callsign */
|
||||
char device_callsign[120]; /* IP address of endpoint in integer form (0.0.0.0 default) */
|
||||
} meshtastic_Contact;
|
||||
|
||||
/* Position Location Information from ATAK */
|
||||
typedef struct _meshtastic_PLI {
|
||||
/* The new preferred location encoding, multiply by 1e-7 to get degrees
|
||||
in floating point */
|
||||
int32_t latitude_i;
|
||||
/* The new preferred location encoding, multiply by 1e-7 to get degrees
|
||||
in floating point */
|
||||
int32_t longitude_i;
|
||||
/* Altitude (ATAK prefers HAE) */
|
||||
uint32_t altitude;
|
||||
/* Speed */
|
||||
uint32_t speed;
|
||||
/* Course in degrees */
|
||||
uint16_t course;
|
||||
} meshtastic_PLI;
|
||||
|
||||
/* Packets for the official ATAK Plugin */
|
||||
typedef struct _meshtastic_TAKPacket {
|
||||
/* Are the payloads strings compressed for LoRA transport? */
|
||||
bool is_compressed;
|
||||
/* The contact / callsign for ATAK user */
|
||||
bool has_contact;
|
||||
meshtastic_Contact contact;
|
||||
/* The group for ATAK user */
|
||||
bool has_group;
|
||||
meshtastic_Group group;
|
||||
/* The status of the ATAK EUD */
|
||||
bool has_status;
|
||||
meshtastic_Status status;
|
||||
pb_size_t which_payload_variant;
|
||||
union {
|
||||
/* TAK position report */
|
||||
meshtastic_PLI pli;
|
||||
/* ATAK GeoChat message */
|
||||
meshtastic_GeoChat chat;
|
||||
} payload_variant;
|
||||
} meshtastic_TAKPacket;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _meshtastic_Team_MIN meshtastic_Team_Unspecifed_Color
|
||||
#define _meshtastic_Team_MAX meshtastic_Team_Brown
|
||||
#define _meshtastic_Team_ARRAYSIZE ((meshtastic_Team)(meshtastic_Team_Brown+1))
|
||||
|
||||
#define _meshtastic_MemberRole_MIN meshtastic_MemberRole_Unspecifed
|
||||
#define _meshtastic_MemberRole_MAX meshtastic_MemberRole_K9
|
||||
#define _meshtastic_MemberRole_ARRAYSIZE ((meshtastic_MemberRole)(meshtastic_MemberRole_K9+1))
|
||||
|
||||
|
||||
|
||||
#define meshtastic_Group_role_ENUMTYPE meshtastic_MemberRole
|
||||
#define meshtastic_Group_team_ENUMTYPE meshtastic_Team
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_TAKPacket_init_default {0, false, meshtastic_Contact_init_default, false, meshtastic_Group_init_default, false, meshtastic_Status_init_default, 0, {meshtastic_PLI_init_default}}
|
||||
#define meshtastic_GeoChat_init_default {"", false, ""}
|
||||
#define meshtastic_Group_init_default {_meshtastic_MemberRole_MIN, _meshtastic_Team_MIN}
|
||||
#define meshtastic_Status_init_default {0}
|
||||
#define meshtastic_Contact_init_default {"", ""}
|
||||
#define meshtastic_PLI_init_default {0, 0, 0, 0, 0}
|
||||
#define meshtastic_TAKPacket_init_zero {0, false, meshtastic_Contact_init_zero, false, meshtastic_Group_init_zero, false, meshtastic_Status_init_zero, 0, {meshtastic_PLI_init_zero}}
|
||||
#define meshtastic_GeoChat_init_zero {"", false, ""}
|
||||
#define meshtastic_Group_init_zero {_meshtastic_MemberRole_MIN, _meshtastic_Team_MIN}
|
||||
#define meshtastic_Status_init_zero {0}
|
||||
#define meshtastic_Contact_init_zero {"", ""}
|
||||
#define meshtastic_PLI_init_zero {0, 0, 0, 0, 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_GeoChat_message_tag 1
|
||||
#define meshtastic_GeoChat_to_tag 2
|
||||
#define meshtastic_Group_role_tag 1
|
||||
#define meshtastic_Group_team_tag 2
|
||||
#define meshtastic_Status_battery_tag 1
|
||||
#define meshtastic_Contact_callsign_tag 1
|
||||
#define meshtastic_Contact_device_callsign_tag 2
|
||||
#define meshtastic_PLI_latitude_i_tag 1
|
||||
#define meshtastic_PLI_longitude_i_tag 2
|
||||
#define meshtastic_PLI_altitude_tag 3
|
||||
#define meshtastic_PLI_speed_tag 4
|
||||
#define meshtastic_PLI_course_tag 5
|
||||
#define meshtastic_TAKPacket_is_compressed_tag 1
|
||||
#define meshtastic_TAKPacket_contact_tag 2
|
||||
#define meshtastic_TAKPacket_group_tag 3
|
||||
#define meshtastic_TAKPacket_status_tag 4
|
||||
#define meshtastic_TAKPacket_pli_tag 5
|
||||
#define meshtastic_TAKPacket_chat_tag 6
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_TAKPacket_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_compressed, 1) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, contact, 2) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, group, 3) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, status, 4) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,pli,payload_variant.pli), 5) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,chat,payload_variant.chat), 6)
|
||||
#define meshtastic_TAKPacket_CALLBACK NULL
|
||||
#define meshtastic_TAKPacket_DEFAULT NULL
|
||||
#define meshtastic_TAKPacket_contact_MSGTYPE meshtastic_Contact
|
||||
#define meshtastic_TAKPacket_group_MSGTYPE meshtastic_Group
|
||||
#define meshtastic_TAKPacket_status_MSGTYPE meshtastic_Status
|
||||
#define meshtastic_TAKPacket_payload_variant_pli_MSGTYPE meshtastic_PLI
|
||||
#define meshtastic_TAKPacket_payload_variant_chat_MSGTYPE meshtastic_GeoChat
|
||||
|
||||
#define meshtastic_GeoChat_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, message, 1) \
|
||||
X(a, STATIC, OPTIONAL, STRING, to, 2)
|
||||
#define meshtastic_GeoChat_CALLBACK NULL
|
||||
#define meshtastic_GeoChat_DEFAULT NULL
|
||||
|
||||
#define meshtastic_Group_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, role, 1) \
|
||||
X(a, STATIC, SINGULAR, UENUM, team, 2)
|
||||
#define meshtastic_Group_CALLBACK NULL
|
||||
#define meshtastic_Group_DEFAULT NULL
|
||||
|
||||
#define meshtastic_Status_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, battery, 1)
|
||||
#define meshtastic_Status_CALLBACK NULL
|
||||
#define meshtastic_Status_DEFAULT NULL
|
||||
|
||||
#define meshtastic_Contact_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, callsign, 1) \
|
||||
X(a, STATIC, SINGULAR, STRING, device_callsign, 2)
|
||||
#define meshtastic_Contact_CALLBACK NULL
|
||||
#define meshtastic_Contact_DEFAULT NULL
|
||||
|
||||
#define meshtastic_PLI_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 1) \
|
||||
X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, altitude, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, speed, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, course, 5)
|
||||
#define meshtastic_PLI_CALLBACK NULL
|
||||
#define meshtastic_PLI_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_TAKPacket_msg;
|
||||
extern const pb_msgdesc_t meshtastic_GeoChat_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Group_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Status_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Contact_msg;
|
||||
extern const pb_msgdesc_t meshtastic_PLI_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_TAKPacket_fields &meshtastic_TAKPacket_msg
|
||||
#define meshtastic_GeoChat_fields &meshtastic_GeoChat_msg
|
||||
#define meshtastic_Group_fields &meshtastic_Group_msg
|
||||
#define meshtastic_Status_fields &meshtastic_Status_msg
|
||||
#define meshtastic_Contact_fields &meshtastic_Contact_msg
|
||||
#define meshtastic_PLI_fields &meshtastic_PLI_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_Contact_size 242
|
||||
#define meshtastic_GeoChat_size 323
|
||||
#define meshtastic_Group_size 4
|
||||
#define meshtastic_PLI_size 26
|
||||
#define meshtastic_Status_size 3
|
||||
#define meshtastic_TAKPacket_size 584
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -45,3 +45,4 @@ PB_BIND(meshtastic_Config_BluetoothConfig, meshtastic_Config_BluetoothConfig, AU
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -108,6 +108,15 @@ typedef enum _meshtastic_Config_PositionConfig_PositionFlags {
|
||||
meshtastic_Config_PositionConfig_PositionFlags_SPEED = 512
|
||||
} meshtastic_Config_PositionConfig_PositionFlags;
|
||||
|
||||
typedef enum _meshtastic_Config_PositionConfig_GpsMode {
|
||||
/* GPS is present but disabled */
|
||||
meshtastic_Config_PositionConfig_GpsMode_DISABLED = 0,
|
||||
/* GPS is present and enabled */
|
||||
meshtastic_Config_PositionConfig_GpsMode_ENABLED = 1,
|
||||
/* GPS is not present on the device */
|
||||
meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT = 2
|
||||
} meshtastic_Config_PositionConfig_GpsMode;
|
||||
|
||||
typedef enum _meshtastic_Config_NetworkConfig_AddressMode {
|
||||
/* obtain ip address via DHCP */
|
||||
meshtastic_Config_NetworkConfig_AddressMode_DHCP = 0,
|
||||
@@ -205,7 +214,9 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode {
|
||||
/* Malaysia 433mhz */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_MY_433 = 16,
|
||||
/* Malaysia 919mhz */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_MY_919 = 17
|
||||
meshtastic_Config_LoRaConfig_RegionCode_MY_919 = 17,
|
||||
/* Singapore 923mhz */
|
||||
meshtastic_Config_LoRaConfig_RegionCode_SG_923 = 18
|
||||
} meshtastic_Config_LoRaConfig_RegionCode;
|
||||
|
||||
/* Standard predefined channel settings
|
||||
@@ -300,6 +311,8 @@ typedef struct _meshtastic_Config_PositionConfig {
|
||||
uint32_t broadcast_smart_minimum_interval_secs;
|
||||
/* (Re)define PIN_GPS_EN for your board. */
|
||||
uint32_t gps_en_gpio;
|
||||
/* Set where GPS is enabled, disabled, or not present */
|
||||
meshtastic_Config_PositionConfig_GpsMode gps_mode;
|
||||
} meshtastic_Config_PositionConfig;
|
||||
|
||||
/* Power Config\
|
||||
@@ -507,6 +520,10 @@ extern "C" {
|
||||
#define _meshtastic_Config_PositionConfig_PositionFlags_MAX meshtastic_Config_PositionConfig_PositionFlags_SPEED
|
||||
#define _meshtastic_Config_PositionConfig_PositionFlags_ARRAYSIZE ((meshtastic_Config_PositionConfig_PositionFlags)(meshtastic_Config_PositionConfig_PositionFlags_SPEED+1))
|
||||
|
||||
#define _meshtastic_Config_PositionConfig_GpsMode_MIN meshtastic_Config_PositionConfig_GpsMode_DISABLED
|
||||
#define _meshtastic_Config_PositionConfig_GpsMode_MAX meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT
|
||||
#define _meshtastic_Config_PositionConfig_GpsMode_ARRAYSIZE ((meshtastic_Config_PositionConfig_GpsMode)(meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT+1))
|
||||
|
||||
#define _meshtastic_Config_NetworkConfig_AddressMode_MIN meshtastic_Config_NetworkConfig_AddressMode_DHCP
|
||||
#define _meshtastic_Config_NetworkConfig_AddressMode_MAX meshtastic_Config_NetworkConfig_AddressMode_STATIC
|
||||
#define _meshtastic_Config_NetworkConfig_AddressMode_ARRAYSIZE ((meshtastic_Config_NetworkConfig_AddressMode)(meshtastic_Config_NetworkConfig_AddressMode_STATIC+1))
|
||||
@@ -528,8 +545,8 @@ extern "C" {
|
||||
#define _meshtastic_Config_DisplayConfig_DisplayMode_ARRAYSIZE ((meshtastic_Config_DisplayConfig_DisplayMode)(meshtastic_Config_DisplayConfig_DisplayMode_COLOR+1))
|
||||
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_MIN meshtastic_Config_LoRaConfig_RegionCode_UNSET
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_MY_919
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_MY_919+1))
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_SG_923
|
||||
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_SG_923+1))
|
||||
|
||||
#define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST
|
||||
#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE
|
||||
@@ -543,6 +560,7 @@ extern "C" {
|
||||
#define meshtastic_Config_DeviceConfig_role_ENUMTYPE meshtastic_Config_DeviceConfig_Role
|
||||
#define meshtastic_Config_DeviceConfig_rebroadcast_mode_ENUMTYPE meshtastic_Config_DeviceConfig_RebroadcastMode
|
||||
|
||||
#define meshtastic_Config_PositionConfig_gps_mode_ENUMTYPE meshtastic_Config_PositionConfig_GpsMode
|
||||
|
||||
|
||||
#define meshtastic_Config_NetworkConfig_address_mode_ENUMTYPE meshtastic_Config_NetworkConfig_AddressMode
|
||||
@@ -562,7 +580,7 @@ extern "C" {
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
|
||||
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
|
||||
#define meshtastic_Config_PowerConfig_init_default {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}
|
||||
@@ -571,7 +589,7 @@ extern "C" {
|
||||
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
|
||||
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
|
||||
#define meshtastic_Config_PowerConfig_init_zero {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}
|
||||
@@ -602,6 +620,7 @@ extern "C" {
|
||||
#define meshtastic_Config_PositionConfig_broadcast_smart_minimum_distance_tag 10
|
||||
#define meshtastic_Config_PositionConfig_broadcast_smart_minimum_interval_secs_tag 11
|
||||
#define meshtastic_Config_PositionConfig_gps_en_gpio_tag 12
|
||||
#define meshtastic_Config_PositionConfig_gps_mode_tag 13
|
||||
#define meshtastic_Config_PowerConfig_is_power_saving_tag 1
|
||||
#define meshtastic_Config_PowerConfig_on_battery_shutdown_after_secs_tag 2
|
||||
#define meshtastic_Config_PowerConfig_adc_multiplier_override_tag 3
|
||||
@@ -704,7 +723,8 @@ X(a, STATIC, SINGULAR, UINT32, rx_gpio, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, tx_gpio, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_distance, 10) \
|
||||
X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_interval_secs, 11) \
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_en_gpio, 12)
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_en_gpio, 12) \
|
||||
X(a, STATIC, SINGULAR, UENUM, gps_mode, 13)
|
||||
#define meshtastic_Config_PositionConfig_CALLBACK NULL
|
||||
#define meshtastic_Config_PositionConfig_DEFAULT NULL
|
||||
|
||||
@@ -810,7 +830,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg;
|
||||
#define meshtastic_Config_LoRaConfig_size 80
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
||||
#define meshtastic_Config_NetworkConfig_size 196
|
||||
#define meshtastic_Config_PositionConfig_size 60
|
||||
#define meshtastic_Config_PositionConfig_size 62
|
||||
#define meshtastic_Config_PowerConfig_size 40
|
||||
#define meshtastic_Config_size 199
|
||||
|
||||
|
||||
@@ -316,7 +316,7 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg;
|
||||
#define meshtastic_DeviceState_size 17062
|
||||
#define meshtastic_NodeInfoLite_size 153
|
||||
#define meshtastic_NodeRemoteHardwarePin_size 29
|
||||
#define meshtastic_OEMStore_size 3244
|
||||
#define meshtastic_OEMStore_size 3246
|
||||
#define meshtastic_PositionLite_size 28
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -180,7 +180,7 @@ 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 467
|
||||
#define meshtastic_LocalConfig_size 469
|
||||
#define meshtastic_LocalModuleConfig_size 631
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -71,6 +71,8 @@ typedef enum _meshtastic_HardwareModel {
|
||||
meshtastic_HardwareModel_SENSELORA_RP2040 = 27,
|
||||
/* Makerfabs SenseLoRA Industrial Monitor (ESP32-S3 + RFM96) */
|
||||
meshtastic_HardwareModel_SENSELORA_S3 = 28,
|
||||
/* Canary Radio Company - CanaryOne: https://canaryradio.io/products/canaryone */
|
||||
meshtastic_HardwareModel_CANARYONE = 29,
|
||||
/* ---------------------------------------------------------------------------
|
||||
Less common/prototype boards listed here (needs one more byte over the air)
|
||||
--------------------------------------------------------------------------- */
|
||||
@@ -125,6 +127,12 @@ typedef enum _meshtastic_HardwareModel {
|
||||
Lora module can be swapped out for a Heltec RA-62 which is "almost" pin compatible
|
||||
with one cut and one jumper Meshtastic works */
|
||||
meshtastic_HardwareModel_CHATTER_2 = 56,
|
||||
/* Heltec Wireless Paper, With ESP32-S3 CPU and E-Ink display
|
||||
Older "V1.0" Variant, has no "version sticker"
|
||||
E-Ink model is DEPG0213BNS800
|
||||
Tab on the screen protector is RED
|
||||
Flex connector marking is FPC-7528B */
|
||||
meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER_V1_0 = 57,
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
@@ -119,6 +119,9 @@ typedef enum _meshtastic_PortNum {
|
||||
/* Aggregates edge info for the network by sending out a list of each node's neighbors
|
||||
ENCODING: Protobuf */
|
||||
meshtastic_PortNum_NEIGHBORINFO_APP = 71,
|
||||
/* ATAK Plugin
|
||||
Portnum for payloads from the official Meshtastic ATAK plugin */
|
||||
meshtastic_PortNum_ATAK_PLUGIN = 72,
|
||||
/* Private applications should use portnums >= 256.
|
||||
To simplify initial development and testing you can use "PRIVATE_APP"
|
||||
in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh)) */
|
||||
|
||||
@@ -398,7 +398,7 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
if (!file.available()) {
|
||||
LOG_WARN("File not available - %s\n", filenameGzip.c_str());
|
||||
res->println("Web server is running.<br><br>The content you are looking for can't be found. Please see: <a "
|
||||
"href=https://meshtastic.org/docs/getting-started/faq#wifi--web-browser>FAQ</a>.<br><br><a "
|
||||
"href=https://meshtastic.org/docs/software/web-client/>FAQ</a>.<br><br><a "
|
||||
"href=/admin>admin</a>");
|
||||
|
||||
return;
|
||||
@@ -854,4 +854,4 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
|
||||
JSONValue *value = new JSONValue(jsonObjOuter);
|
||||
res->print(value->Stringify().c_str());
|
||||
delete value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include <FSCommon.h>
|
||||
#ifdef ARCH_ESP32
|
||||
#include "BleOta.h"
|
||||
#endif
|
||||
@@ -194,6 +195,15 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_delete_file_request_tag: {
|
||||
LOG_DEBUG("Client is requesting to delete file: %s\n", r->delete_file_request);
|
||||
if (FSCom.remove(r->delete_file_request)) {
|
||||
LOG_DEBUG("Successfully deleted file\n");
|
||||
} else {
|
||||
LOG_DEBUG("Failed to delete file\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef ARCH_PORTDUINO
|
||||
case meshtastic_AdminMessage_exit_simulator_tag:
|
||||
LOG_INFO("Exiting simulator\n");
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
#include "AtakPluginModule.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "meshtastic/atak.pb.h"
|
||||
|
||||
extern "C" {
|
||||
#include "mesh/compression/unishox2.h"
|
||||
}
|
||||
|
||||
AtakPluginModule *atakPluginModule;
|
||||
|
||||
AtakPluginModule::AtakPluginModule()
|
||||
: ProtobufModule("atak", meshtastic_PortNum_ATAK_PLUGIN, &meshtastic_TAKPacket_msg), concurrency::OSThread("AtakPluginModule")
|
||||
{
|
||||
ourPortNum = meshtastic_PortNum_ATAK_PLUGIN;
|
||||
}
|
||||
|
||||
/*
|
||||
Encompasses the full construction and sending packet to mesh
|
||||
Will be used for broadcast.
|
||||
*/
|
||||
int32_t AtakPluginModule::runOnce()
|
||||
{
|
||||
return default_broadcast_interval_secs;
|
||||
}
|
||||
|
||||
bool AtakPluginModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_TAKPacket *r)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
meshtastic_TAKPacket AtakPluginModule::cloneTAKPacketData(meshtastic_TAKPacket *t)
|
||||
{
|
||||
meshtastic_TAKPacket clone = meshtastic_TAKPacket_init_zero;
|
||||
if (t->has_group) {
|
||||
clone.has_group = true;
|
||||
clone.group = t->group;
|
||||
}
|
||||
if (t->has_status) {
|
||||
clone.has_status = true;
|
||||
clone.status = t->status;
|
||||
}
|
||||
if (t->has_contact) {
|
||||
clone.has_contact = true;
|
||||
clone.contact = {0};
|
||||
}
|
||||
|
||||
if (t->which_payload_variant == meshtastic_TAKPacket_pli_tag) {
|
||||
clone.which_payload_variant = meshtastic_TAKPacket_pli_tag;
|
||||
clone.payload_variant.pli = t->payload_variant.pli;
|
||||
} else if (t->which_payload_variant == meshtastic_TAKPacket_chat_tag) {
|
||||
clone.which_payload_variant = meshtastic_TAKPacket_chat_tag;
|
||||
clone.payload_variant.chat = {0};
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
void AtakPluginModule::alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtastic_TAKPacket *t)
|
||||
{
|
||||
// From Phone (EUD)
|
||||
if (mp.from == 0) {
|
||||
LOG_DEBUG("Received uncompressed TAK payload from phone with %d bytes\n", mp.decoded.payload.size);
|
||||
// Compress for LoRA transport
|
||||
auto compressed = cloneTAKPacketData(t);
|
||||
compressed.is_compressed = true;
|
||||
if (t->has_contact) {
|
||||
auto length = unishox2_compress_simple(t->contact.callsign, strlen(t->contact.callsign), compressed.contact.callsign);
|
||||
LOG_DEBUG("Uncompressed callsign '%s' - %d bytes\n", t->contact.callsign, strlen(t->contact.callsign));
|
||||
LOG_DEBUG("Compressed callsign '%s' - %d bytes\n", t->contact.callsign, length);
|
||||
|
||||
length = unishox2_compress_simple(t->contact.device_callsign, strlen(t->contact.device_callsign),
|
||||
compressed.contact.device_callsign);
|
||||
LOG_DEBUG("Uncompressed device_callsign '%s' - %d bytes\n", t->contact.device_callsign,
|
||||
strlen(t->contact.device_callsign));
|
||||
LOG_DEBUG("Compressed device_callsign '%s' - %d bytes\n", compressed.contact.device_callsign, length);
|
||||
}
|
||||
if (t->which_payload_variant == meshtastic_TAKPacket_chat_tag) {
|
||||
auto length = unishox2_compress_simple(t->payload_variant.chat.message, strlen(t->payload_variant.chat.message),
|
||||
compressed.payload_variant.chat.message);
|
||||
LOG_DEBUG("Uncompressed chat message '%s' - %d bytes\n", t->payload_variant.chat.message,
|
||||
strlen(t->payload_variant.chat.message));
|
||||
LOG_DEBUG("Compressed chat message '%s' - %d bytes\n", compressed.payload_variant.chat.message, length);
|
||||
|
||||
if (t->payload_variant.chat.has_to) {
|
||||
compressed.payload_variant.chat.has_to = true;
|
||||
length = unishox2_compress_simple(t->payload_variant.chat.to, strlen(t->payload_variant.chat.to),
|
||||
compressed.payload_variant.chat.to);
|
||||
LOG_DEBUG("Uncompressed chat to '%s' - %d bytes\n", t->payload_variant.chat.to,
|
||||
strlen(t->payload_variant.chat.to));
|
||||
LOG_DEBUG("Compressed chat to '%s' - %d bytes\n", compressed.payload_variant.chat.to, length);
|
||||
}
|
||||
}
|
||||
mp.decoded.payload.size = pb_encode_to_bytes(mp.decoded.payload.bytes, sizeof(mp.decoded.payload.bytes),
|
||||
meshtastic_TAKPacket_fields, &compressed);
|
||||
LOG_DEBUG("Final payload size of %d bytes\n", mp.decoded.payload.size);
|
||||
} else {
|
||||
if (!t->is_compressed) {
|
||||
// Not compressed. Something is wrong
|
||||
LOG_ERROR("Received uncompressed TAKPacket over radio!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Decompress for Phone (EUD)
|
||||
auto decompressedCopy = packetPool.allocCopy(mp);
|
||||
auto uncompressed = cloneTAKPacketData(t);
|
||||
uncompressed.is_compressed = false;
|
||||
if (t->has_contact) {
|
||||
auto length =
|
||||
unishox2_decompress_simple(t->contact.callsign, strlen(t->contact.callsign), uncompressed.contact.callsign);
|
||||
|
||||
LOG_DEBUG("Compressed callsign: %d bytes\n", strlen(t->contact.callsign));
|
||||
LOG_DEBUG("Decompressed callsign: '%s' @ %d bytes\n", uncompressed.contact.callsign, length);
|
||||
|
||||
length = unishox2_decompress_simple(t->contact.device_callsign, strlen(t->contact.device_callsign),
|
||||
uncompressed.contact.device_callsign);
|
||||
|
||||
LOG_DEBUG("Compressed device_callsign: %d bytes\n", strlen(t->contact.device_callsign));
|
||||
LOG_DEBUG("Decompressed device_callsign: '%s' @ %d bytes\n", uncompressed.contact.device_callsign, length);
|
||||
}
|
||||
if (uncompressed.which_payload_variant == meshtastic_TAKPacket_chat_tag) {
|
||||
auto length = unishox2_decompress_simple(t->payload_variant.chat.message, strlen(t->payload_variant.chat.message),
|
||||
uncompressed.payload_variant.chat.message);
|
||||
LOG_DEBUG("Compressed chat message: %d bytes\n", strlen(t->payload_variant.chat.message));
|
||||
LOG_DEBUG("Decompressed chat message: '%s' @ %d bytes\n", uncompressed.payload_variant.chat.message, length);
|
||||
|
||||
if (t->payload_variant.chat.has_to) {
|
||||
uncompressed.payload_variant.chat.has_to = true;
|
||||
length = unishox2_decompress_simple(t->payload_variant.chat.to, strlen(t->payload_variant.chat.to),
|
||||
uncompressed.payload_variant.chat.to);
|
||||
LOG_DEBUG("Compressed chat to: %d bytes\n", strlen(t->payload_variant.chat.to));
|
||||
LOG_DEBUG("Decompressed chat to: '%s' @ %d bytes\n", uncompressed.payload_variant.chat.to, length);
|
||||
}
|
||||
}
|
||||
decompressedCopy->decoded.payload.size =
|
||||
pb_encode_to_bytes(decompressedCopy->decoded.payload.bytes, sizeof(decompressedCopy->decoded.payload),
|
||||
meshtastic_TAKPacket_fields, &uncompressed);
|
||||
|
||||
service.sendToPhone(decompressedCopy);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include "ProtobufModule.h"
|
||||
#include "meshtastic/atak.pb.h"
|
||||
|
||||
/**
|
||||
* Waypoint message handling for meshtastic
|
||||
*/
|
||||
class AtakPluginModule : public ProtobufModule<meshtastic_TAKPacket>, private concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
/** Constructor
|
||||
* name is for debugging output
|
||||
*/
|
||||
AtakPluginModule();
|
||||
|
||||
protected:
|
||||
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_TAKPacket *t) override;
|
||||
virtual void alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtastic_TAKPacket *t) override;
|
||||
/* Does our periodic broadcast */
|
||||
int32_t runOnce() override;
|
||||
|
||||
private:
|
||||
meshtastic_TAKPacket cloneTAKPacketData(meshtastic_TAKPacket *t);
|
||||
};
|
||||
|
||||
extern AtakPluginModule *atakPluginModule;
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "input/cardKbI2cImpl.h"
|
||||
#include "input/kbMatrixImpl.h"
|
||||
#include "modules/AdminModule.h"
|
||||
#include "modules/AtakPluginModule.h"
|
||||
#include "modules/CannedMessageModule.h"
|
||||
#include "modules/DetectionSensorModule.h"
|
||||
#include "modules/NeighborInfoModule.h"
|
||||
@@ -61,7 +62,7 @@ void setupModules()
|
||||
traceRouteModule = new TraceRouteModule();
|
||||
neighborInfoModule = new NeighborInfoModule();
|
||||
detectionSensorModule = new DetectionSensorModule();
|
||||
|
||||
atakPluginModule = new AtakPluginModule();
|
||||
// Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
|
||||
// to a global variable.
|
||||
|
||||
|
||||
@@ -204,6 +204,8 @@ int32_t PositionModule::runOnce()
|
||||
}
|
||||
|
||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
|
||||
if (node == nullptr)
|
||||
return RUNONCE_INTERVAL;
|
||||
|
||||
// We limit our GPS broadcasts to a max rate
|
||||
uint32_t now = millis();
|
||||
|
||||
+78
-66
@@ -17,7 +17,6 @@
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
#include "mqtt/JSON.h"
|
||||
#include <assert.h>
|
||||
|
||||
const int reconnectMax = 5;
|
||||
@@ -49,34 +48,32 @@ void MQTT::onReceive(char *topic, byte *payload, size_t length)
|
||||
payloadStr[length] = 0; // null terminated string
|
||||
JSONValue *json_value = JSON::Parse(payloadStr);
|
||||
if (json_value != NULL) {
|
||||
LOG_INFO("JSON Received on MQTT, parsing..\n");
|
||||
|
||||
// check if it is a valid envelope
|
||||
JSONObject json;
|
||||
json = json_value->AsObject();
|
||||
|
||||
// parse the channel name from the topic string
|
||||
char *ptr = strtok(topic, "/");
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ptr = strtok(NULL, "/");
|
||||
}
|
||||
// parse the channel name from the topic string by looking for "json/"
|
||||
const char *jsonSlash = "json/";
|
||||
char *ptr = strstr(topic, jsonSlash) + sizeof(jsonSlash) + 1; // set pointer to after "json/"
|
||||
ptr = strtok(ptr, "/") ? strtok(ptr, "/") : ptr; // if another "/" was added, parse string up to that character
|
||||
meshtastic_Channel sendChannel = channels.getByName(ptr);
|
||||
LOG_DEBUG("Found Channel name: %s (Index %d)\n", channels.getGlobalId(sendChannel.index), sendChannel.index);
|
||||
// We allow downlink JSON packets only on a channel named "mqtt"
|
||||
if (strncasecmp(channels.getGlobalId(sendChannel.index), Channels::mqttChannel, strlen(Channels::mqttChannel)) == 0 &&
|
||||
sendChannel.settings.downlink_enabled) {
|
||||
if (isValidJsonEnvelope(json)) {
|
||||
// this is a valid envelope
|
||||
if (json["type"]->AsString().compare("sendtext") == 0 && json["payload"]->IsString()) {
|
||||
std::string jsonPayloadStr = json["payload"]->AsString();
|
||||
LOG_INFO("JSON payload %s, length %u\n", jsonPayloadStr.c_str(), jsonPayloadStr.length());
|
||||
|
||||
if ((json.find("sender") != json.end()) && (json.find("payload") != json.end()) &&
|
||||
(json.find("type") != json.end()) && json["type"]->IsString() &&
|
||||
(json["type"]->AsString().compare("sendtext") == 0)) {
|
||||
// this is a valid envelope
|
||||
if (json["payload"]->IsString() && json["type"]->IsString() &&
|
||||
(json["sender"]->AsString().compare(owner.id) != 0)) {
|
||||
std::string jsonPayloadStr = json["payload"]->AsString();
|
||||
LOG_INFO("JSON payload %s, length %u\n", jsonPayloadStr.c_str(), jsonPayloadStr.length());
|
||||
|
||||
// construct protobuf data packet using TEXT_MESSAGE, send it to the mesh
|
||||
meshtastic_MeshPacket *p = router->allocForSending();
|
||||
p->decoded.portnum = meshtastic_PortNum_TEXT_MESSAGE_APP;
|
||||
p->channel = sendChannel.index;
|
||||
if (sendChannel.settings.downlink_enabled) {
|
||||
// construct protobuf data packet using TEXT_MESSAGE, send it to the mesh
|
||||
meshtastic_MeshPacket *p = router->allocForSending();
|
||||
p->decoded.portnum = meshtastic_PortNum_TEXT_MESSAGE_APP;
|
||||
if (json.find("channel") != json.end() && json["channel"]->IsNumber() &&
|
||||
(json["channel"]->AsNumber() < channels.getNumChannels()))
|
||||
p->channel = json["channel"]->AsNumber();
|
||||
if (json.find("to") != json.end() && json["to"]->IsNumber())
|
||||
p->to = json["to"]->AsNumber();
|
||||
if (jsonPayloadStr.length() <= sizeof(p->decoded.payload.bytes)) {
|
||||
memcpy(p->decoded.payload.bytes, jsonPayloadStr.c_str(), jsonPayloadStr.length());
|
||||
p->decoded.payload.size = jsonPayloadStr.length();
|
||||
@@ -85,61 +82,65 @@ void MQTT::onReceive(char *topic, byte *payload, size_t length)
|
||||
} else {
|
||||
LOG_WARN("Received MQTT json payload too long, dropping\n");
|
||||
}
|
||||
} else {
|
||||
LOG_WARN("Received MQTT json payload on channel %s, but downlink is disabled, dropping\n",
|
||||
sendChannel.settings.name);
|
||||
}
|
||||
} else {
|
||||
LOG_DEBUG("JSON Ignoring downlink message we originally sent.\n");
|
||||
}
|
||||
} else if ((json.find("sender") != json.end()) && (json.find("payload") != json.end()) &&
|
||||
(json.find("type") != json.end()) && json["type"]->IsString() &&
|
||||
(json["type"]->AsString().compare("sendposition") == 0)) {
|
||||
// invent the "sendposition" type for a valid envelope
|
||||
if (json["payload"]->IsObject() && json["type"]->IsString() &&
|
||||
(json["sender"]->AsString().compare(owner.id) != 0)) {
|
||||
JSONObject posit;
|
||||
posit = json["payload"]->AsObject(); // get nested JSON Position
|
||||
meshtastic_Position pos = meshtastic_Position_init_default;
|
||||
pos.latitude_i = posit["latitude_i"]->AsNumber();
|
||||
pos.longitude_i = posit["longitude_i"]->AsNumber();
|
||||
pos.altitude = posit["altitude"]->AsNumber();
|
||||
pos.time = posit["time"]->AsNumber();
|
||||
} else if (json["type"]->AsString().compare("sendposition") == 0 && json["payload"]->IsObject()) {
|
||||
// invent the "sendposition" type for a valid envelope
|
||||
JSONObject posit;
|
||||
posit = json["payload"]->AsObject(); // get nested JSON Position
|
||||
meshtastic_Position pos = meshtastic_Position_init_default;
|
||||
if (posit.find("latitude_i") != posit.end() && posit["latitude_i"]->IsNumber())
|
||||
pos.latitude_i = posit["latitude_i"]->AsNumber();
|
||||
if (posit.find("longitude_i") != posit.end() && posit["longitude_i"]->IsNumber())
|
||||
pos.longitude_i = posit["longitude_i"]->AsNumber();
|
||||
if (posit.find("altitude") != posit.end() && posit["altitude"]->IsNumber())
|
||||
pos.altitude = posit["altitude"]->AsNumber();
|
||||
if (posit.find("time") != posit.end() && posit["time"]->IsNumber())
|
||||
pos.time = posit["time"]->AsNumber();
|
||||
|
||||
// construct protobuf data packet using POSITION, send it to the mesh
|
||||
meshtastic_MeshPacket *p = router->allocForSending();
|
||||
p->decoded.portnum = meshtastic_PortNum_POSITION_APP;
|
||||
p->channel = sendChannel.index;
|
||||
if (sendChannel.settings.downlink_enabled) {
|
||||
// construct protobuf data packet using POSITION, send it to the mesh
|
||||
meshtastic_MeshPacket *p = router->allocForSending();
|
||||
p->decoded.portnum = meshtastic_PortNum_POSITION_APP;
|
||||
if (json.find("channel") != json.end() && json["channel"]->IsNumber() &&
|
||||
(json["channel"]->AsNumber() < channels.getNumChannels()))
|
||||
p->channel = json["channel"]->AsNumber();
|
||||
if (json.find("to") != json.end() && json["to"]->IsNumber())
|
||||
p->to = json["to"]->AsNumber();
|
||||
p->decoded.payload.size =
|
||||
pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes),
|
||||
&meshtastic_Position_msg, &pos); // make the Data protobuf from position
|
||||
service.sendToMesh(p, RX_SRC_LOCAL);
|
||||
} else {
|
||||
LOG_WARN("Received MQTT json payload on channel %s, but downlink is disabled, dropping\n",
|
||||
sendChannel.settings.name);
|
||||
LOG_DEBUG("JSON Ignoring downlink message with unsupported type.\n");
|
||||
}
|
||||
} else {
|
||||
LOG_DEBUG("JSON Ignoring downlink message we originally sent.\n");
|
||||
LOG_ERROR("JSON Received payload on MQTT but not a valid envelope.\n");
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR("JSON Received payload on MQTT but not a valid envelope\n");
|
||||
LOG_WARN("JSON downlink received on channel not called 'mqtt' or without downlink enabled.\n");
|
||||
}
|
||||
} else {
|
||||
// no json, this is an invalid payload
|
||||
LOG_ERROR("Invalid MQTT service envelope, topic %s, len %u!\n", topic, length);
|
||||
LOG_ERROR("JSON Received payload on MQTT but not a valid JSON\n");
|
||||
}
|
||||
delete json_value;
|
||||
} else {
|
||||
if (!pb_decode_from_bytes(payload, length, &meshtastic_ServiceEnvelope_msg, &e)) {
|
||||
if (length == 0) {
|
||||
LOG_WARN("Empty MQTT payload received, topic %s!\n", topic);
|
||||
return;
|
||||
} else if (!pb_decode_from_bytes(payload, length, &meshtastic_ServiceEnvelope_msg, &e)) {
|
||||
LOG_ERROR("Invalid MQTT service envelope, topic %s, len %u!\n", topic, length);
|
||||
return;
|
||||
} else {
|
||||
if (strcmp(e.gateway_id, owner.id) == 0)
|
||||
LOG_INFO("Ignoring downlink message we originally sent.\n");
|
||||
else {
|
||||
meshtastic_Channel ch = channels.getByName(e.channel_id);
|
||||
if (strcmp(e.gateway_id, owner.id) == 0) {
|
||||
// Generate an implicit ACK towards ourselves (handled and processed only locally!) for this message.
|
||||
// We do this because packets are not rebroadcasted back into MQTT anymore and we assume that at least one node
|
||||
// receives it when we get our own packet back. Then we'll stop our retransmissions.
|
||||
if (e.packet && getFrom(e.packet) == nodeDB.getNodeNum())
|
||||
routingModule->sendAckNak(meshtastic_Routing_Error_NONE, getFrom(e.packet), e.packet->id, ch.index);
|
||||
else
|
||||
LOG_INFO("Ignoring downlink message we originally sent.\n");
|
||||
} else {
|
||||
// Find channel by channel_id and check downlink_enabled
|
||||
meshtastic_Channel ch = channels.getByName(e.channel_id);
|
||||
if (strcmp(e.channel_id, channels.getGlobalId(ch.index)) == 0 && e.packet && ch.settings.downlink_enabled) {
|
||||
LOG_INFO("Received MQTT topic %s, len=%u\n", topic, length);
|
||||
meshtastic_MeshPacket *p = packetPool.allocCopy(*e.packet);
|
||||
@@ -463,7 +464,7 @@ void MQTT::publishQueuedMessages()
|
||||
}
|
||||
}
|
||||
|
||||
void MQTT::onSend(const meshtastic_MeshPacket &mp, ChannelIndex chIndex)
|
||||
void MQTT::onSend(const meshtastic_MeshPacket &mp, const meshtastic_MeshPacket &mp_decoded, ChannelIndex chIndex)
|
||||
{
|
||||
if (mp.via_mqtt)
|
||||
return; // Don't send messages that came from MQTT back into MQTT
|
||||
@@ -483,7 +484,13 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp, ChannelIndex chIndex)
|
||||
meshtastic_ServiceEnvelope *env = mqttPool.allocZeroed();
|
||||
env->channel_id = (char *)channelId;
|
||||
env->gateway_id = owner.id;
|
||||
env->packet = (meshtastic_MeshPacket *)∓
|
||||
|
||||
if (moduleConfig.mqtt.encryption_enabled) {
|
||||
env->packet = (meshtastic_MeshPacket *)∓
|
||||
} else {
|
||||
env->packet = (meshtastic_MeshPacket *)&mp_decoded;
|
||||
}
|
||||
|
||||
LOG_DEBUG("MQTT onSend - Publishing portnum %i message\n", env->packet->decoded.portnum);
|
||||
|
||||
if (moduleConfig.mqtt.proxy_to_client_enabled || this->isConnectedDirectly()) {
|
||||
@@ -498,7 +505,7 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp, ChannelIndex chIndex)
|
||||
|
||||
if (moduleConfig.mqtt.json_enabled) {
|
||||
// handle json topic
|
||||
auto jsonString = this->meshPacketToJson((meshtastic_MeshPacket *)&mp);
|
||||
auto jsonString = this->meshPacketToJson((meshtastic_MeshPacket *)&mp_decoded);
|
||||
if (jsonString.length() != 0) {
|
||||
std::string topicJson = jsonTopic + channelId + "/" + owner.id;
|
||||
LOG_INFO("JSON publish message to %s, %u bytes: %s\n", topicJson.c_str(), jsonString.length(),
|
||||
@@ -507,11 +514,6 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp, ChannelIndex chIndex)
|
||||
}
|
||||
}
|
||||
|
||||
// Generate an implicit ACK towards ourselves (handled and processed only locally!) for this message.
|
||||
// We do this because packets are not rebroadcasted back into MQTT anymore and we assume that at least one node
|
||||
// receives it when we're connected to the broker. Then we'll stop our retransmissions.
|
||||
if (getFrom(&mp) == nodeDB.getNodeNum())
|
||||
routingModule->sendAckNak(meshtastic_Routing_Error_NONE, getFrom(&mp), mp.id, chIndex);
|
||||
} else {
|
||||
LOG_INFO("MQTT not connected, queueing packet\n");
|
||||
if (mqttQueue.numFree() == 0) {
|
||||
@@ -809,4 +811,14 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
|
||||
|
||||
delete value;
|
||||
return jsonStr;
|
||||
}
|
||||
|
||||
bool MQTT::isValidJsonEnvelope(JSONObject &json)
|
||||
{
|
||||
// if "sender" is provided, avoid processing packets we uplinked
|
||||
return (json.find("sender") != json.end() ? (json["sender"]->AsString().compare(owner.id) != 0) : true) &&
|
||||
(json.find("from") != json.end()) && json["from"]->IsNumber() &&
|
||||
(json["from"]->AsNumber() == nodeDB.getNodeNum()) && // only accept message if the "from" is us
|
||||
(json.find("type") != json.end()) && json["type"]->IsString() && // should specify a type
|
||||
(json.find("payload") != json.end()); // should have a payload
|
||||
}
|
||||
+6
-2
@@ -5,6 +5,7 @@
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "mesh/Channels.h"
|
||||
#include "mesh/generated/meshtastic/mqtt.pb.h"
|
||||
#include "mqtt/JSON.h"
|
||||
#if HAS_WIFI
|
||||
#include <WiFiClient.h>
|
||||
#define HAS_NETWORKING 1
|
||||
@@ -48,14 +49,14 @@ class MQTT : private concurrency::OSThread
|
||||
MQTT();
|
||||
|
||||
/**
|
||||
* Publish a packet on the glboal MQTT server.
|
||||
* Publish a packet on the global MQTT server.
|
||||
* This hook must be called **after** the packet is encrypted (including the channel being changed to a hash).
|
||||
* @param chIndex the index of the channel for this message
|
||||
*
|
||||
* Note: for messages we are forwarding on the mesh that we can't find the channel for (because we don't have the keys), we
|
||||
* can not forward those messages to the cloud - because no way to find a global channel ID.
|
||||
*/
|
||||
void onSend(const meshtastic_MeshPacket &mp, ChannelIndex chIndex);
|
||||
void onSend(const meshtastic_MeshPacket &mp, const meshtastic_MeshPacket &mp_decoded, ChannelIndex chIndex);
|
||||
|
||||
/** Attempt to connect to server if necessary
|
||||
*/
|
||||
@@ -100,6 +101,9 @@ class MQTT : private concurrency::OSThread
|
||||
void publishStatus();
|
||||
void publishQueuedMessages();
|
||||
|
||||
// returns true if this is a valid JSON envelope which we accept on downlink
|
||||
bool isValidJsonEnvelope(JSONObject &json);
|
||||
|
||||
/// Return 0 if sleep is okay, veto sleep if we are connected to pubsub server
|
||||
// int preflightSleepCb(void *unused = NULL) { return pubSub.connected() ? 1 : 0; }
|
||||
};
|
||||
|
||||
@@ -107,6 +107,8 @@
|
||||
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WSL_V3
|
||||
#elif defined(HELTEC_WIRELESS_TRACKER)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER
|
||||
#elif defined(HELTEC_WIRELESS_PAPER_V1_0)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER_V1_0
|
||||
#elif defined(HELTEC_WIRELESS_PAPER)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER
|
||||
#elif defined(TLORA_T3S3_V1)
|
||||
@@ -125,6 +127,8 @@
|
||||
#define HW_VENDOR meshtastic_HardwareModel_SENSELORA_S3
|
||||
#elif defined(HELTEC_HT62)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_HT62
|
||||
#elif defined(CHATTER_2)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_CHATTER_2
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -175,7 +175,8 @@ void cpuDeepSleep(uint32_t msecToWake)
|
||||
some current will flow through these external and internal resistors, increasing deep
|
||||
sleep current above the minimal possible value.
|
||||
|
||||
Note: we don't isolate pins that are used for the LORA, LED, i2c, spi or the wake button
|
||||
Note: we don't isolate pins that are used for the LORA, LED, i2c, or ST7735 Display for the Chatter2, spi or the wake
|
||||
button(s), maybe we should not include any other GPIOs...
|
||||
*/
|
||||
#if SOC_RTCIO_HOLD_SUPPORTED
|
||||
static const uint8_t rtcGpios[] = {/* 0, */ 2,
|
||||
@@ -184,9 +185,9 @@ void cpuDeepSleep(uint32_t msecToWake)
|
||||
13,
|
||||
/* 14, */ /* 15, */
|
||||
#endif
|
||||
/* 25, */ 26, /* 27, */
|
||||
32, 33, 34, 35,
|
||||
36, 37
|
||||
/* 25, */ /* 26, */ /* 27, */
|
||||
/* 32, */ /* 33, */ 34, 35,
|
||||
/* 36, */ 37
|
||||
/* 38, 39 */};
|
||||
|
||||
for (int i = 0; i < sizeof(rtcGpios); i++)
|
||||
|
||||
@@ -81,6 +81,7 @@ void portduinoSetup()
|
||||
YAML::Node yamlConfig;
|
||||
|
||||
if (configPath != nullptr) {
|
||||
std::cout << "Using " << configPath << " as config file" << std::endl;
|
||||
try {
|
||||
yamlConfig = YAML::LoadFile(configPath);
|
||||
} catch (YAML::Exception e) {
|
||||
@@ -88,6 +89,7 @@ void portduinoSetup()
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (access("config.yaml", R_OK) == 0) {
|
||||
std::cout << "Using local config.yaml as config file" << std::endl;
|
||||
try {
|
||||
yamlConfig = YAML::LoadFile("config.yaml");
|
||||
} catch (YAML::Exception e) {
|
||||
@@ -95,6 +97,7 @@ void portduinoSetup()
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (access("/etc/meshtasticd/config.yaml", R_OK) == 0) {
|
||||
std::cout << "Using /etc/meshtasticd/config.yaml as config file" << std::endl;
|
||||
try {
|
||||
yamlConfig = YAML::LoadFile("/etc/meshtasticd/config.yaml");
|
||||
} catch (YAML::Exception e) {
|
||||
@@ -105,24 +108,21 @@ void portduinoSetup()
|
||||
std::cout << "No 'config.yaml' found, running simulated." << std::endl;
|
||||
// Set the random seed equal to TCPPort to have a different seed per instance
|
||||
randomSeed(TCPPort);
|
||||
|
||||
/* Aren't all pins defaulted to simulated?
|
||||
auto fakeBusy = new SimGPIOPin(SX126X_BUSY, "fakeBusy");
|
||||
fakeBusy->writePin(LOW);
|
||||
fakeBusy->setSilent(true);
|
||||
gpioBind(fakeBusy);
|
||||
|
||||
auto cs = new SimGPIOPin(SX126X_CS, "fakeLoraCS");
|
||||
cs->setSilent(true);
|
||||
gpioBind(cs);
|
||||
|
||||
gpioBind(new SimGPIOPin(SX126X_RESET, "fakeLoraReset"));
|
||||
gpioBind(new SimGPIOPin(LORA_DIO1, "fakeLoraIrq"));
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (yamlConfig["Logging"]) {
|
||||
if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "debug") {
|
||||
settingsMap[logoutputlevel] = level_debug;
|
||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "info") {
|
||||
settingsMap[logoutputlevel] = level_info;
|
||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "warn") {
|
||||
settingsMap[logoutputlevel] = level_warn;
|
||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "error") {
|
||||
settingsMap[logoutputlevel] = level_error;
|
||||
}
|
||||
}
|
||||
if (yamlConfig["Lora"]) {
|
||||
settingsMap[use_sx1262] = false;
|
||||
settingsMap[use_rf95] = false;
|
||||
@@ -158,6 +158,9 @@ void portduinoSetup()
|
||||
settingsMap[has_gps] = 1;
|
||||
}
|
||||
}
|
||||
if (yamlConfig["I2C"]) {
|
||||
settingsStrings[i2cdev] = yamlConfig["I2C"]["I2CDevice"].as<std::string>("");
|
||||
}
|
||||
settingsMap[displayPanel] = no_screen;
|
||||
if (yamlConfig["Display"]) {
|
||||
if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7789")
|
||||
@@ -166,6 +169,8 @@ void portduinoSetup()
|
||||
settingsMap[displayPanel] = st7735;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7735S")
|
||||
settingsMap[displayPanel] = st7735s;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9341")
|
||||
settingsMap[displayPanel] = ili9341;
|
||||
settingsMap[displayHeight] = yamlConfig["Display"]["Height"].as<int>(0);
|
||||
settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as<int>(0);
|
||||
settingsMap[displayDC] = yamlConfig["Display"]["DC"].as<int>(-1);
|
||||
@@ -181,6 +186,8 @@ void portduinoSetup()
|
||||
if (yamlConfig["Touchscreen"]) {
|
||||
if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "XPT2046")
|
||||
settingsMap[touchscreenModule] = xpt2046;
|
||||
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "STMPE610")
|
||||
settingsMap[touchscreenModule] = stmpe610;
|
||||
settingsMap[touchscreenCS] = yamlConfig["Touchscreen"]["CS"].as<int>(-1);
|
||||
settingsMap[touchscreenIRQ] = yamlConfig["Touchscreen"]["IRQ"].as<int>(-1);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ enum configNames {
|
||||
user,
|
||||
gpiochip,
|
||||
spidev,
|
||||
i2cdev,
|
||||
has_gps,
|
||||
touchscreenModule,
|
||||
touchscreenCS,
|
||||
@@ -31,10 +32,12 @@ enum configNames {
|
||||
displayOffsetX,
|
||||
displayOffsetY,
|
||||
displayInvert,
|
||||
keyboardDevice
|
||||
keyboardDevice,
|
||||
logoutputlevel
|
||||
};
|
||||
enum { no_screen, st7789, st7735, st7735s };
|
||||
enum { no_touchscreen, xpt2046 };
|
||||
enum { no_screen, st7789, st7735, st7735s, ili9341 };
|
||||
enum { no_touchscreen, xpt2046, stmpe610 };
|
||||
enum { level_error, level_warn, level_info, level_debug };
|
||||
|
||||
extern std::map<configNames, int> settingsMap;
|
||||
extern std::map<configNames, std::string> settingsStrings;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
; CircuitMess Chatter 2 based on ESP32-WROOM-32 (38 pins) devkit & DeeamLNK DL-LLCC68 or Heltec HT RA62 SX1262/SX1268 module
|
||||
[env:chatter2]
|
||||
extends = esp32_base
|
||||
board = esp32doit-devkit-v1
|
||||
board_level = extra
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D CHATTER_2
|
||||
-I variants/chatter2
|
||||
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
lovyan03/LovyanGFX@^1.1.8
|
||||
@@ -0,0 +1,118 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Have custom connections or functionality? Configure them in this section //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Debugging
|
||||
// #define GPS_DEBUG
|
||||
// #define GPS_EXTRAVERBOSE
|
||||
|
||||
// Lora
|
||||
#define USE_LLCC68 // Original Chatter2 with LLCC68 module
|
||||
#define USE_SX1262 // Added for when Lora module is swapped for HT-RA62
|
||||
|
||||
#define SX126X_CS 14 // module's NSS pin
|
||||
#define LORA_SCK 16 // module's SCK pin
|
||||
#define LORA_MOSI 5 // module's MOSI pin
|
||||
#define LORA_MISO 17 // module's MISO pin
|
||||
#define SX126X_RESET RADIOLIB_NC // module's NRST pin
|
||||
#define SX126X_BUSY 4 // module's BUSY pin works for both LLCC68 and RA-62 with cut & jumper
|
||||
#define SX126X_DIO1 18 // module's DIO1 pin
|
||||
#define SX126X_DIO2_AS_RF_SWITCH // module's DIO2 pin
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8 // module's DIO pin
|
||||
#define SX126X_TXEN RADIOLIB_NC
|
||||
#define SX126X_RXEN RADIOLIB_NC
|
||||
|
||||
// Status
|
||||
// #define LED_PIN 1
|
||||
// External notification
|
||||
// FIXME: Check if EXT_NOTIFY_OUT actualy has any effect and removes the need for setting the external notication pin in the
|
||||
// app/preferences
|
||||
// #define EXT_NOTIFY_OUT 2 // The GPIO pin that acts as the external notification output (here we connect an LED to it)
|
||||
|
||||
// Buzzer
|
||||
#define PIN_BUZZER 19
|
||||
// Buttons
|
||||
#define BUTTON_PIN 36 // Use the WAKE button as the user button
|
||||
// I2C
|
||||
// #define I2C_SCL 27
|
||||
// #define I2C_SDA 26
|
||||
|
||||
#define SX126X_MAX_POWER 22 // SX126xInterface.cpp defaults to 22 if not defined, but here we define it for good practice
|
||||
|
||||
// Display
|
||||
|
||||
#define HAS_SCREEN 1 // Assume no screen present by default to prevent crash...
|
||||
|
||||
// ST7735S TFT LCD
|
||||
#define ST7735S 1 // there are different (sub-)versions of ST7735
|
||||
#define ST7735_CS -1
|
||||
#define ST7735_RS 33 // DC
|
||||
#define ST7735_SDA 26 // MOSI
|
||||
#define ST7735_SCK 27
|
||||
#define ST7735_RESET 15
|
||||
#define ST7735_MISO -1
|
||||
#define ST7735_BUSY -1
|
||||
#define ST7735_BL 32
|
||||
#define ST7735_SPI_HOST HSPI_HOST // SPI2_HOST for S3, auto may work too
|
||||
#define SPI_FREQUENCY 40000000
|
||||
#define SPI_READ_FREQUENCY 16000000
|
||||
#define TFT_HEIGHT 160
|
||||
#define TFT_WIDTH 128
|
||||
#define TFT_OFFSET_X 0
|
||||
#define TFT_OFFSET_Y 0
|
||||
#define TFT_INVERT false
|
||||
#define SCREEN_ROTATE
|
||||
#define SCREEN_TRANSITION_FRAMERATE 5 // fps
|
||||
#define DISPLAY_FORCE_SMALL_FONTS
|
||||
|
||||
// Battery
|
||||
|
||||
#define BATTERY_PIN 34 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
|
||||
#define ADC_CHANNEL ADC1_GPIO34_CHANNEL
|
||||
#define ADC_ATTENUATION \
|
||||
ADC_ATTEN_DB_2_5 // 2_5-> 100mv-1250mv, 11-> 150mv-3100mv for ESP32
|
||||
// ESP32-S2/C3/S3 are different
|
||||
// lower dB for lower voltage rnage
|
||||
#define ADC_MULTIPLIER \
|
||||
5.0 // VBATT---10k--pin34---2.5K---GND
|
||||
// Chatter2 uses 3 AAA cells
|
||||
#define BAT_FULLVOLT 4800 // with the 5.0 divider, input to BATTERY_PIN is 900mv
|
||||
#define BAT_EMPTYVOLT 3300
|
||||
#undef EXT_PWR_DETECT
|
||||
|
||||
// GPS
|
||||
// FIXME: unsure what to define HAS_GPS as if GPS isn't always present
|
||||
#define HAS_GPS 1 // Don't need to set this to 0 to prevent a crash as it doesn't crash if GPS not found, will probe by default
|
||||
// #define PIN_GPS_EN 15
|
||||
// #define GPS_EN_ACTIVE 1
|
||||
#undef GPS_TX_PIN
|
||||
#undef GPS_RX_PIN
|
||||
#define GPS_TX_PIN 13
|
||||
#define GPS_RX_PIN 2
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// You should have no need to modify the code below, nor in pins_arduino.h //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define LORA_CS SX126X_CS // FIXME: for some reason both are used in /src
|
||||
|
||||
// Many of the below values would only be used if USE_RF95 was defined, but it's not as we aren't actually using an RF95, just
|
||||
// that the 4 pins above are named like it If they aren't used they don't need to be defined and doing so cause confusion to those
|
||||
// adapting this file LORA_RESET value is never used in src (as we are not using RF95), so no need to define LORA_DIO0 is not used
|
||||
// in src (as we are not using RF95) as SX1262 does not have it per SX1262 datasheet, so no need to define
|
||||
// FIXME: confirm that the linked lines below are actually only called when using the SX126x or SX128x and no other modules
|
||||
// then use SX126X_DIO1 and SX128X_DIO1 respectively for that purpose, removing the need for RF95-style LORA_* definitions when
|
||||
// the RF95 isn't used
|
||||
#define LORA_DIO1 \
|
||||
SX126X_DIO1 // The old name is used in
|
||||
// https://github.com/meshtastic/firmware/blob/7eff5e7bcb2084499b723c5e3846c15ee089e36d/src/sleep.cpp#L298, so
|
||||
// must also define the old name
|
||||
// LORA_DIO2 value is never used in src (as we are not using RF95), so no need to define, and if DIO2_AS_RF_SWITCH is set then it
|
||||
// cannot serve any extra function even if requested to LORA_DIO3 value is never used in src (as we are not using RF95), so no
|
||||
// need to define, and DIO3_AS_TCXO_AT_1V8 is set so it cannot serve any extra function even if requested to (from 13.3.2.1
|
||||
// DioxMask in SX1262 datasheet: Note that if DIO2 or DIO3 are used to control the RF Switch or the TCXO, the IRQ will not be
|
||||
// generated even if it is mapped to the pins.)
|
||||
@@ -0,0 +1,78 @@
|
||||
#ifndef Pins_Arduino_h
|
||||
#define Pins_Arduino_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define WIFI_Kit_32 true
|
||||
#define DISPLAY_HEIGHT 64
|
||||
#define DISPLAY_WIDTH 128
|
||||
|
||||
#define EXTERNAL_NUM_INTERRUPTS 16
|
||||
#define NUM_DIGITAL_PINS 40
|
||||
#define NUM_ANALOG_INPUTS 16
|
||||
|
||||
#define analogInputToDigitalPin(p) (((p) < 20) ? (analogChannelToDigitalPin(p)) : -1)
|
||||
#define digitalPinToInterrupt(p) (((p) < 40) ? (p) : -1)
|
||||
#define digitalPinHasPWM(p) (p < 34)
|
||||
|
||||
static const uint8_t LED_BUILTIN = 35;
|
||||
#define BUILTIN_LED LED_BUILTIN // backward compatibility
|
||||
#define LED_BUILTIN LED_BUILTIN
|
||||
|
||||
static const uint8_t KEY_BUILTIN = 0;
|
||||
|
||||
static const uint8_t TX = 43;
|
||||
static const uint8_t RX = 44;
|
||||
|
||||
static const uint8_t SDA = 41;
|
||||
static const uint8_t SCL = 42;
|
||||
|
||||
static const uint8_t SS = 8;
|
||||
static const uint8_t MOSI = 10;
|
||||
static const uint8_t MISO = 11;
|
||||
static const uint8_t SCK = 9;
|
||||
|
||||
static const uint8_t A0 = 1;
|
||||
static const uint8_t A1 = 2;
|
||||
static const uint8_t A2 = 3;
|
||||
static const uint8_t A3 = 4;
|
||||
static const uint8_t A4 = 5;
|
||||
static const uint8_t A5 = 6;
|
||||
static const uint8_t A6 = 7;
|
||||
static const uint8_t A7 = 8;
|
||||
static const uint8_t A8 = 9;
|
||||
static const uint8_t A9 = 10;
|
||||
static const uint8_t A10 = 11;
|
||||
static const uint8_t A11 = 12;
|
||||
static const uint8_t A12 = 13;
|
||||
static const uint8_t A13 = 14;
|
||||
static const uint8_t A14 = 15;
|
||||
static const uint8_t A15 = 16;
|
||||
static const uint8_t A16 = 17;
|
||||
static const uint8_t A17 = 18;
|
||||
static const uint8_t A18 = 19;
|
||||
static const uint8_t A19 = 20;
|
||||
|
||||
static const uint8_t T1 = 1;
|
||||
static const uint8_t T2 = 2;
|
||||
static const uint8_t T3 = 3;
|
||||
static const uint8_t T4 = 4;
|
||||
static const uint8_t T5 = 5;
|
||||
static const uint8_t T6 = 6;
|
||||
static const uint8_t T7 = 7;
|
||||
static const uint8_t T8 = 8;
|
||||
static const uint8_t T9 = 9;
|
||||
static const uint8_t T10 = 10;
|
||||
static const uint8_t T11 = 11;
|
||||
static const uint8_t T12 = 12;
|
||||
static const uint8_t T13 = 13;
|
||||
static const uint8_t T14 = 14;
|
||||
|
||||
static const uint8_t Vext = 45;
|
||||
static const uint8_t LED = 18;
|
||||
|
||||
static const uint8_t RST_LoRa = 12;
|
||||
static const uint8_t BUSY_LoRa = 13;
|
||||
static const uint8_t DIO0 = 14;
|
||||
|
||||
#endif /* Pins_Arduino_h */
|
||||
@@ -0,0 +1,13 @@
|
||||
[env:heltec-wireless-paper-v1_0]
|
||||
extends = esp32s3_base
|
||||
board = heltec_wifi_lora_32_V3
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags}
|
||||
-I variants/heltec_wireless_paper_v1
|
||||
-D HELTEC_WIRELESS_PAPER_V1_0
|
||||
lib_deps =
|
||||
${esp32s3_base.lib_deps}
|
||||
https://github.com/meshtastic/GxEPD2/
|
||||
adafruit/Adafruit BusIO@^1.13.2
|
||||
lewisxhe/PCF8563_Library@^1.0.1
|
||||
upload_speed = 115200
|
||||
@@ -0,0 +1,54 @@
|
||||
#define LED_PIN 18
|
||||
|
||||
// Enable bus for external periherals
|
||||
#define I2C_SDA SDA
|
||||
#define I2C_SCL SCL
|
||||
|
||||
#define USE_EINK
|
||||
/*
|
||||
* eink display pins
|
||||
*/
|
||||
#define PIN_EINK_CS 4
|
||||
#define PIN_EINK_BUSY 7
|
||||
#define PIN_EINK_DC 5
|
||||
#define PIN_EINK_RES 6
|
||||
#define PIN_EINK_SCLK 3
|
||||
#define PIN_EINK_MOSI 2
|
||||
|
||||
/*
|
||||
* SPI interfaces
|
||||
*/
|
||||
#define SPI_INTERFACES_COUNT 2
|
||||
|
||||
#define PIN_SPI_MISO 10 // MISO P0.17
|
||||
#define PIN_SPI_MOSI 11 // MOSI P0.15
|
||||
#define PIN_SPI_SCK 9 // SCK P0.13
|
||||
|
||||
#define VEXT_ENABLE 45 // active low, powers the oled display and the lora antenna boost
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
#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
|
||||
|
||||
#define LORA_DIO0 -1 // a No connect on the SX1262 module
|
||||
#define LORA_RESET 12
|
||||
#define LORA_DIO1 14 // SX1262 IRQ
|
||||
#define LORA_DIO2 13 // SX1262 BUSY
|
||||
#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled
|
||||
|
||||
#define LORA_SCK 9
|
||||
#define LORA_MISO 11
|
||||
#define LORA_MOSI 10
|
||||
#define LORA_CS 8
|
||||
|
||||
#define SX126X_CS LORA_CS
|
||||
#define SX126X_DIO1 LORA_DIO1
|
||||
#define SX126X_BUSY LORA_DIO2
|
||||
#define SX126X_RESET LORA_RESET
|
||||
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
@@ -80,6 +80,7 @@ static const uint8_t A5 = PIN_A5;
|
||||
// Other pins
|
||||
#define PIN_AREF PIN_A5
|
||||
#define PIN_VBAT PIN_A4
|
||||
#define BATTERY_PIN PIN_VBAT
|
||||
#define PIN_NFC1 (33)
|
||||
#define PIN_NFC2 (2)
|
||||
#define PIN_PIEZO (37)
|
||||
|
||||
@@ -100,6 +100,7 @@ static const uint8_t A5 = PIN_A5;
|
||||
// Other pins
|
||||
#define PIN_AREF PIN_A5
|
||||
#define PIN_VBAT PIN_A4
|
||||
#define BATTERY_PIN PIN_VBAT
|
||||
#define PIN_NFC1 (33)
|
||||
#define PIN_NFC2 (2)
|
||||
#define PIN_PIEZO (37)
|
||||
|
||||
@@ -170,7 +170,7 @@ External serial flash W25Q16JV_IQ
|
||||
// Voltage divider value => 100K + 100K voltage divider on VBAT = (100K / (100K + 100K))
|
||||
#define VBAT_DIVIDER (0.5F)
|
||||
// Compensation factor for the VBAT divider
|
||||
#define VBAT_DIVIDER_COMP (2.0)
|
||||
#define VBAT_DIVIDER_COMP (2.0F)
|
||||
// Fixed calculation of milliVolt from compensation value
|
||||
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
|
||||
#undef AREF_VOLTAGE
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
#define HAS_WIRE 1
|
||||
#define HAS_SCREEN 1
|
||||
#define CANNED_MESSAGE_MODULE_ENABLE 1
|
||||
@@ -56,6 +56,8 @@ static const uint8_t SCK = 33;
|
||||
#define LED_PIN LED_BLUE
|
||||
|
||||
#define PIN_VBAT WB_A0
|
||||
#define BATTERY_PIN PIN_VBAT
|
||||
#define ADC_CHANNEL ADC1_GPIO36_CHANNEL
|
||||
|
||||
// https://docs.rakwireless.com/Product-Categories/WisBlock/RAK13300/
|
||||
|
||||
|
||||
@@ -10,4 +10,6 @@ build_flags = ${rp2040_base.build_flags}
|
||||
-DDEBUG_RP2040_PORT=Serial
|
||||
-L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m0plus"
|
||||
lib_deps =
|
||||
${rp2040_base.lib_deps}
|
||||
${rp2040_base.lib_deps}
|
||||
debug_build_flags = ${rp2040_base.build_flags}
|
||||
debug_tool = cmsis-dap ; for e.g. Picotool
|
||||
@@ -12,6 +12,7 @@
|
||||
// #define EXT_NOTIFY_OUT 4
|
||||
|
||||
#define BATTERY_PIN 26
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS ADC_RESOLUTION
|
||||
// ratio of voltage divider = 3.0 (R17=200k, R18=100k)
|
||||
#define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
|
||||
// Voltage divider value => 1.5M + 1M voltage divider on VBAT = (1.5M / (1M + 1.5M))
|
||||
#define VBAT_DIVIDER (0.4F)
|
||||
// Compensation factor for the VBAT divider
|
||||
#define VBAT_DIVIDER_COMP (1.73)
|
||||
#define VBAT_DIVIDER_COMP (1.73F)
|
||||
// Fixed calculation of milliVolt from compensation value
|
||||
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
|
||||
#undef AREF_VOLTAGE
|
||||
|
||||
@@ -223,7 +223,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
|
||||
// Voltage divider value => 1.5M + 1M voltage divider on VBAT = (1.5M / (1M + 1.5M))
|
||||
#define VBAT_DIVIDER (0.4F)
|
||||
// Compensation factor for the VBAT divider
|
||||
#define VBAT_DIVIDER_COMP (1.73)
|
||||
#define VBAT_DIVIDER_COMP (1.73F)
|
||||
// Fixed calculation of milliVolt from compensation value
|
||||
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
|
||||
#undef AREF_VOLTAGE
|
||||
|
||||
@@ -11,4 +11,6 @@ build_flags = ${rp2040_base.build_flags}
|
||||
-DHW_SPI1_DEVICE
|
||||
-L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m0plus"
|
||||
lib_deps =
|
||||
${rp2040_base.lib_deps}
|
||||
${rp2040_base.lib_deps}
|
||||
debug_build_flags = ${rp2040_base.build_flags}
|
||||
debug_tool = cmsis-dap ; for e.g. Picotool
|
||||
@@ -22,6 +22,7 @@
|
||||
#define BATTERY_PIN 26
|
||||
// ratio of voltage divider = 3.0 (R17=200k, R18=100k)
|
||||
#define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS ADC_RESOLUTION
|
||||
|
||||
#define USE_SX1262
|
||||
|
||||
|
||||
@@ -14,4 +14,6 @@ build_flags = ${rp2040_base.build_flags}
|
||||
build_src_filter = ${rp2040_base.build_src_filter} +<mesh/wifi/>
|
||||
lib_deps =
|
||||
${rp2040_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
debug_build_flags = ${rp2040_base.build_flags}
|
||||
debug_tool = cmsis-dap ; for e.g. Picotool
|
||||
@@ -24,6 +24,7 @@
|
||||
#define BATTERY_PIN 26
|
||||
// ratio of voltage divider = 3.0 (R17=200k, R18=100k)
|
||||
#define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS ADC_RESOLUTION
|
||||
|
||||
#define USE_SX1262
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define LED_PIN PIN_LED
|
||||
|
||||
#undef BATTERY_PIN
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS ADC_RESOLUTION
|
||||
|
||||
#undef LORA_SCK
|
||||
#undef LORA_MISO
|
||||
|
||||
@@ -6,6 +6,7 @@ debug_tool = jlink
|
||||
|
||||
# add -DCFG_SYSVIEW if you want to use the Segger systemview tool for OS profiling.
|
||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/t-echo
|
||||
-DGPS_POWER_TOGGLE
|
||||
-L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m4/fpv4-sp-d16-hard"
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/t-echo>
|
||||
lib_deps =
|
||||
|
||||
@@ -213,7 +213,7 @@ External serial flash WP25R1635FZUIL0
|
||||
// Voltage divider value => 100K + 100K voltage divider on VBAT = (100K / (100K + 100K))
|
||||
#define VBAT_DIVIDER (0.5F)
|
||||
// Compensation factor for the VBAT divider
|
||||
#define VBAT_DIVIDER_COMP (2.0)
|
||||
#define VBAT_DIVIDER_COMP (2.0F)
|
||||
// Fixed calculation of milliVolt from compensation value
|
||||
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
|
||||
#undef AREF_VOLTAGE
|
||||
|
||||
@@ -16,5 +16,13 @@
|
||||
#define USE_RF95
|
||||
#define LORA_DIO0 26 // a No connect on the SX1262 module
|
||||
#define LORA_RESET 23
|
||||
|
||||
// In the T3 V1.6.1 TXCO version, GPIO 33 is connected to Radio’s
|
||||
// internal temperature-compensated crystal oscillator enable
|
||||
#ifdef LORA_TCXO_GPIO
|
||||
#define LORA_DIO1 RADIOLIB_NC // no-connect on sx127x module
|
||||
#else
|
||||
#define LORA_DIO1 33 // https://www.thethingsnetwork.org/forum/t/big-esp32-sx127x-topic-part-3/18436
|
||||
#endif
|
||||
|
||||
#define LORA_DIO2 32 // Not really used
|
||||
@@ -0,0 +1,9 @@
|
||||
[env:tlora-v2-1-1_6-tcxo]
|
||||
extends = esp32_base
|
||||
board = ttgo-lora32-v21
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D TLORA_V2_1_16
|
||||
-I variants/tlora_v2_1_16
|
||||
-D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||
-D LORA_TCXO_GPIO=33
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
[VERSION]
|
||||
major = 2
|
||||
minor = 2
|
||||
build = 19
|
||||
build = 22
|
||||
|
||||
Reference in New Issue
Block a user