mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-03 16:41:56 +00:00
Compare commits
42 Commits
v1.3.5.e5b
...
v1.3.7.bb2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb22b6ec58 | ||
|
|
ddb9678377 | ||
|
|
dc20cbb672 | ||
|
|
a10ea604af | ||
|
|
fb1caa51d0 | ||
|
|
7e977aea00 | ||
|
|
ecc114f1cd | ||
|
|
b76424db50 | ||
|
|
f511baba9a | ||
|
|
b056081d3c | ||
|
|
0e4699d8b6 | ||
|
|
794167c701 | ||
|
|
b59368ca3c | ||
|
|
a4bdef4151 | ||
|
|
478274aff1 | ||
|
|
02066cc8b9 | ||
|
|
309de52f5c | ||
|
|
340737f2a8 | ||
|
|
9bd970c55e | ||
|
|
6eab8f84d1 | ||
|
|
a31bf71ec1 | ||
|
|
14eef42762 | ||
|
|
ef85b74cec | ||
|
|
16ae867c2d | ||
|
|
0643dcd745 | ||
|
|
69ed477040 | ||
|
|
0f5b0b5f00 | ||
|
|
11323acb23 | ||
|
|
a20ba7e686 | ||
|
|
10a7071300 | ||
|
|
eae9673ddb | ||
|
|
6e9cf82b68 | ||
|
|
0035469790 | ||
|
|
028999697e | ||
|
|
b7aa1397c7 | ||
|
|
279def7911 | ||
|
|
d73d3ca959 | ||
|
|
998c90d326 | ||
|
|
0c600363c8 | ||
|
|
6c2d45d866 | ||
|
|
cf532496a4 | ||
|
|
92d32f722d |
1
.github/workflows/main_matrix.yml
vendored
1
.github/workflows/main_matrix.yml
vendored
@@ -162,6 +162,7 @@ jobs:
|
||||
- board: rak4631_19003
|
||||
- board: rak4631_5005_eink
|
||||
- board: t-echo
|
||||
- board: pca10059_diy_eink
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
6
.github/workflows/update_protobufs.yml
vendored
6
.github/workflows/update_protobufs.yml
vendored
@@ -17,9 +17,9 @@ jobs:
|
||||
|
||||
- name: Download nanopb
|
||||
run: |
|
||||
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.4-linux-x86.tar.gz
|
||||
tar xvzf nanopb-0.4.4-linux-x86.tar.gz
|
||||
mv nanopb-0.4.4-linux-x86 nanopb-0.4.4
|
||||
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.5-linux-x86.tar.gz
|
||||
tar xvzf nanopb-0.4.5-linux-x86.tar.gz
|
||||
mv nanopb-0.4.5-linux-x86 nanopb-0.4.5
|
||||
|
||||
- name: Re-generate protocol buffers
|
||||
run: |
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
[](https://open.vscode.dev/meshtastic/Meshtastic-device)
|
||||
[](https://github.com/meshtastic/Meshtastic-device/actions/workflows/main.yml)
|
||||

|
||||
[](https://cla-assistant.io/meshtastic/Meshtastic-device)
|
||||
|
||||
## This repository contains the device firmware used in the [Meshtastic](https://meshtastic.org) project.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ BOARDS_ESP32="rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-
|
||||
#BOARDS_ESP32=tbeam
|
||||
|
||||
# FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine
|
||||
BOARDS_NRF52="rak4631_5005 rak4631_5005_eink rak4631_19003 t-echo"
|
||||
BOARDS_NRF52="rak4631_5005 rak4631_5005_eink rak4631_19003 t-echo pca10059_diy_eink"
|
||||
#BOARDS_NRF52=""
|
||||
|
||||
OUTDIR=release/latest
|
||||
|
||||
@@ -13,7 +13,7 @@ if [[ $# -gt 0 ]]; then
|
||||
# can override which environment by passing arg
|
||||
BOARDS="$@"
|
||||
else
|
||||
BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631_5005 rak4631_19003 rak11200 t-echo"
|
||||
BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631_5005 rak4631_19003 rak11200 t-echo pca10059_diy_eink"
|
||||
fi
|
||||
|
||||
echo "BOARDS:${BOARDS}"
|
||||
|
||||
72
boards/nordic_pca10059.json
Normal file
72
boards/nordic_pca10059.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [
|
||||
[
|
||||
"0x239A",
|
||||
"0x8029"
|
||||
],
|
||||
[
|
||||
"0x239A",
|
||||
"0x0029"
|
||||
],
|
||||
[
|
||||
"0x239A",
|
||||
"0x002A"
|
||||
],
|
||||
[
|
||||
"0x239A",
|
||||
"0x802A"
|
||||
]
|
||||
],
|
||||
"usb_product": "PCA10059",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "nRF52840 Dongle",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": [
|
||||
"bluetooth"
|
||||
],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"svd_path": "nrf52840.svd"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"name": "nRF52840 Dongle",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"speed": 115200,
|
||||
"protocol": "nrfutil",
|
||||
"protocols": [
|
||||
"jlink",
|
||||
"nrfjprog",
|
||||
"nrfutil",
|
||||
"stlink"
|
||||
],
|
||||
"use_1200bps_touch": true,
|
||||
"require_upload_port": true,
|
||||
"wait_for_upload_port": true
|
||||
},
|
||||
"url": "https://www.nordicsemi.com/Products/Development-hardware/nrf52840-dongle",
|
||||
"vendor": "Nordic Semiconductor"
|
||||
}
|
||||
@@ -19,6 +19,8 @@ default_envs = tbeam
|
||||
;default_envs = rak4631_5005
|
||||
;default_envs = rak4631_5005_eink
|
||||
;default_envs = rak4631_19003
|
||||
;default_envs = nano-g1
|
||||
;default_envs = pca10059_diy_eink
|
||||
;default_envs = meshtastic-diy-v1
|
||||
;default_envs = meshtastic-diy-v1.1
|
||||
|
||||
@@ -40,13 +42,13 @@ build_flags = -Wno-missing-field-initializers
|
||||
monitor_speed = 921600
|
||||
|
||||
lib_deps =
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#53580644255b48ebb7a737343c6b4e71c7e11cf2 ; ESP8266_SSD1306
|
||||
mathertel/OneButton@^2.0.3 ; OneButton library for non-blocking button debounce
|
||||
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
|
||||
https://github.com/meshtastic/arduino-fsm.git
|
||||
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad
|
||||
https://github.com/meshtastic/RadioLib.git#5582ac30578ff3f53f20630a00b2a8a4b8f92c74
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#f0f47067ef2f67c856475933188251c1ef615e79
|
||||
https://github.com/meshtastic/TinyGPSPlus.git
|
||||
https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460
|
||||
Wire ; explicitly needed here because the AXP202 library forgets to add it
|
||||
SPI
|
||||
@@ -108,11 +110,15 @@ lib_ignore =
|
||||
ESP32 BLE Arduino
|
||||
platform_packages =
|
||||
framework-arduinoespressif32@https://github.com/meshtastic/arduino-esp32.git#4cde0f5d412d2695184f32e8a47e9bea57b45276
|
||||
; leave this commented out to avoid breaking Windows
|
||||
|
||||
; leave this commented out to avoid breaking Windows
|
||||
;upload_port = /dev/ttyUSB0
|
||||
;monitor_port = /dev/ttyUSB0
|
||||
|
||||
; Please don't delete these lines. JM uses them.
|
||||
;upload_port = /dev/cu.SLAB_USBtoUART
|
||||
;monitor_port = /dev/cu.SLAB_USBtoUART
|
||||
|
||||
; customize the partition table
|
||||
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
|
||||
board_build.partitions = partition-table.csv
|
||||
@@ -157,4 +163,4 @@ extends = nrf52_base
|
||||
board = rak815
|
||||
debug_tool = jlink
|
||||
upload_protocol = jlink
|
||||
monitor_speed = 115200
|
||||
monitor_speed = 115200
|
||||
|
||||
2
proto
2
proto
Submodule proto updated: 31eaff0924...870a62b27e
@@ -11,13 +11,13 @@ template <class T> class Observable;
|
||||
*/
|
||||
template <class T> class Observer
|
||||
{
|
||||
Observable<T> *observed = NULL;
|
||||
std::list<Observable<T> *> observed;
|
||||
|
||||
public:
|
||||
virtual ~Observer();
|
||||
|
||||
/// Stop watching our current obserable
|
||||
void unobserve();
|
||||
/// Stop watching the obserable
|
||||
void unobserve(Observable<T> *o);
|
||||
|
||||
/// Start watching a specified observable
|
||||
void observe(Observable<T> *o);
|
||||
@@ -87,21 +87,21 @@ template <class T> class Observable
|
||||
|
||||
template <class T> Observer<T>::~Observer()
|
||||
{
|
||||
unobserve();
|
||||
for (typename std::list<Observable<T> *>::const_iterator iterator = observed.begin(); iterator != observed.end();
|
||||
++iterator) {
|
||||
(*iterator)->removeObserver(this);
|
||||
}
|
||||
observed.clear();
|
||||
}
|
||||
|
||||
template <class T> void Observer<T>::unobserve()
|
||||
template <class T> void Observer<T>::unobserve(Observable<T> *o)
|
||||
{
|
||||
if (observed)
|
||||
observed->removeObserver(this);
|
||||
observed = NULL;
|
||||
o->removeObserver(this);
|
||||
observed.remove(o);
|
||||
}
|
||||
|
||||
template <class T> void Observer<T>::observe(Observable<T> *o)
|
||||
{
|
||||
// We can only watch one thing at a time
|
||||
assert(!observed);
|
||||
|
||||
observed = o;
|
||||
observed.push_back(o);
|
||||
o->addObserver(this);
|
||||
}
|
||||
|
||||
@@ -363,9 +363,6 @@ void PowerFSM_setup()
|
||||
|
||||
if (meshSds != UINT32_MAX)
|
||||
powerFSM.add_timed_transition(lowPowerState, &stateSDS, meshSds * 1000, NULL, "mesh timeout");
|
||||
// removing for now, because some users don't even have phones
|
||||
// powerFSM.add_timed_transition(lowPowerState, &stateSDS, getPref_phone_sds_timeout_sec() * 1000, NULL, "phone
|
||||
// timeout");
|
||||
|
||||
powerFSM.run_machine(); // run one interation of the state machine, so we run our on enter tasks for the initial DARK state
|
||||
}
|
||||
|
||||
@@ -125,6 +125,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define RTC_DATA_ATTR
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Feature toggles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Disable use of the NTP library and related features
|
||||
//#define DISABLE_NTP
|
||||
|
||||
// Disable the welcome screen and allow
|
||||
#define DISABLE_WELCOME_UNSET
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// OLED & Input
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -240,6 +250,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#define HW_VENDOR HardwareModel_T_ECHO
|
||||
|
||||
#elif defined(NANO_G1)
|
||||
|
||||
#define HW_VENDOR HardwareModel_NANO_G1
|
||||
|
||||
#elif defined(NORDIC_PCA10059)
|
||||
|
||||
#define HW_VENDOR HardwareModel_NRF52840_PCA10059
|
||||
|
||||
#elif NRF52_SERIES
|
||||
|
||||
#define HW_VENDOR HardwareModel_NRF52_UNKNOWN
|
||||
|
||||
@@ -15,7 +15,7 @@ uint8_t oled_probe(byte addr)
|
||||
r = Wire.read();
|
||||
}
|
||||
r &= 0x0f;
|
||||
if (r == 0x08) {
|
||||
if (r == 0x08 || r == 0x00) {
|
||||
o_probe = 2; // SH1106
|
||||
} else if ( r == 0x03 || r == 0x06 || r == 0x07) {
|
||||
o_probe = 1; // SSD1306
|
||||
|
||||
@@ -41,6 +41,25 @@ bool GPS::setupGPS()
|
||||
#endif
|
||||
#ifndef NO_ESP32
|
||||
_serial_gps->setRxBufferSize(2048); // the default is 256
|
||||
#endif
|
||||
#ifdef TTGO_T_ECHO
|
||||
// Switch to 4800 baud, then close and reopen port
|
||||
_serial_gps->write("$PCAS01,0*1C\r\n");
|
||||
delay(250);
|
||||
_serial_gps->end();
|
||||
delay(250);
|
||||
_serial_gps->begin(4800);
|
||||
delay(250);
|
||||
// Initialize the L76K Chip, use GPS + GLONASS
|
||||
_serial_gps->write("$PCAS04,5*1C\r\n");
|
||||
delay(250);
|
||||
// only ask for RMC and GGA
|
||||
_serial_gps->write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n");
|
||||
delay(250);
|
||||
// Switch to Vehicle Mode, since SoftRF enables Aviation < 2g
|
||||
_serial_gps->write("$PCAS11,3*1E\r\n");
|
||||
delay(250);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -76,8 +95,8 @@ bool GPS::setup()
|
||||
GPS::~GPS()
|
||||
{
|
||||
// we really should unregister our sleep observer
|
||||
notifySleepObserver.unobserve();
|
||||
notifyDeepSleepObserver.unobserve();
|
||||
notifySleepObserver.unobserve(¬ifySleep);
|
||||
notifyDeepSleepObserver.unobserve(¬ifyDeepSleep);
|
||||
}
|
||||
|
||||
bool GPS::hasLock() { return hasValidLocation; }
|
||||
|
||||
@@ -25,6 +25,11 @@
|
||||
//1.54 inch 200x200 - GxEPD2_154_M09
|
||||
//#define TECHO_DISPLAY_MODEL GxEPD2_154_M09
|
||||
|
||||
#elif defined(PCA10059)
|
||||
|
||||
//4.2 inch 300x400 - GxEPD2_420_M01
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_420_M01
|
||||
|
||||
#endif
|
||||
|
||||
GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay;
|
||||
@@ -47,6 +52,11 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl)
|
||||
//GxEPD2_154_M09
|
||||
//setGeometry(GEOMETRY_RAWMODE, 200, 200);
|
||||
|
||||
#elif defined(PCA10059)
|
||||
|
||||
//GxEPD2_420_M01
|
||||
setGeometry(GEOMETRY_RAWMODE, 300, 400);
|
||||
|
||||
#endif
|
||||
// setGeometry(GEOMETRY_RAWMODE, 128, 64); // old resolution
|
||||
// setGeometry(GEOMETRY_128_64); // We originally used this because I wasn't sure if rawmode worked - it does
|
||||
@@ -71,8 +81,8 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
|
||||
// FIXME - only draw bits have changed (use backbuf similar to the other displays)
|
||||
// tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK);
|
||||
for (uint64_t y = 0; y < displayHeight; y++) {
|
||||
for (uint64_t x = 0; x < displayWidth; x++) {
|
||||
for (uint32_t y = 0; y < displayHeight; y++) {
|
||||
for (uint32_t x = 0; x < displayWidth; x++) {
|
||||
|
||||
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent
|
||||
auto b = buffer[x + (y / 8) * displayWidth];
|
||||
@@ -81,11 +91,7 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(TTGO_T_ECHO)
|
||||
DEBUG_MSG("Updating T-ECHO E-Paper... ");
|
||||
#elif defined(RAK4630)
|
||||
DEBUG_MSG("Updating RAK4361_5005 E-Paper... ");
|
||||
#endif
|
||||
DEBUG_MSG("Updating E-Paper... ");
|
||||
|
||||
#if defined(TTGO_T_ECHO)
|
||||
// ePaper.Reset(); // wake the screen from sleep
|
||||
@@ -101,6 +107,8 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
// 4.2 inch 300x400 - GxEPD2_420_M01
|
||||
//adafruitDisplay->nextPage();
|
||||
|
||||
#elif defined(PCA10059)
|
||||
adafruitDisplay->nextPage();
|
||||
#endif
|
||||
|
||||
// Put screen to sleep to save power (possibly not necessary because we already did poweroff inside of display)
|
||||
@@ -176,6 +184,14 @@ bool EInkDisplay::connect()
|
||||
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
}
|
||||
#elif defined(PCA10059)
|
||||
{
|
||||
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
|
||||
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
||||
adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
adafruitDisplay->setRotation(3);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -168,6 +168,28 @@ static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
}
|
||||
}
|
||||
|
||||
// Used when booting without a region set
|
||||
static void drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->drawString(64 + x, y, "Meshtastic :)");
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2 - 3, "Set the region using the");
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 3 - 3, "Meshtastic Android, iOS,");
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "Flasher or CLI client.");
|
||||
|
||||
#ifndef NO_ESP32
|
||||
yield();
|
||||
esp_task_wdt_reset();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef HAS_EINK
|
||||
/// Used on eink displays while in deep sleep
|
||||
static void drawSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
@@ -256,7 +278,7 @@ static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *sta
|
||||
display->drawString(0 + x, 0 + y, tempBuf);
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_SMALL);
|
||||
display->drawString(0 + x, FONT_HEIGHT_MEDIUM + y, "For help, please post on\nmeshtastic.discourse.group");
|
||||
display->drawString(0 + x, FONT_HEIGHT_MEDIUM + y, "For help, please visit \nmeshtastic.org");
|
||||
}
|
||||
|
||||
// Ignore messages orginating from phone (from the current node 0x0) unless range test or store and forward module are enabled
|
||||
@@ -646,8 +668,18 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
snprintf(lastStr, sizeof(lastStr), "%u seconds ago", agoSecs);
|
||||
else if (agoSecs < 120 * 60) // last 2 hrs
|
||||
snprintf(lastStr, sizeof(lastStr), "%u minutes ago", agoSecs / 60);
|
||||
else
|
||||
snprintf(lastStr, sizeof(lastStr), "%u hours ago", agoSecs / 60 / 60);
|
||||
else {
|
||||
|
||||
uint32_t hours_in_month = 730;
|
||||
|
||||
// Only show hours ago if it's been less than 6 months. Otherwise, we may have bad
|
||||
// data.
|
||||
if ((agoSecs / 60 / 60) < (hours_in_month * 6)) {
|
||||
snprintf(lastStr, sizeof(lastStr), "%u hours ago", agoSecs / 60 / 60);
|
||||
} else {
|
||||
snprintf(lastStr, sizeof(lastStr), "unknown age");
|
||||
}
|
||||
}
|
||||
|
||||
static char distStr[20];
|
||||
strcpy(distStr, "? km"); // might not have location data
|
||||
@@ -766,7 +798,7 @@ void Screen::setup()
|
||||
useDisplay = true;
|
||||
|
||||
#ifdef AutoOLEDWire_h
|
||||
dispdev.setDetected(screen_model);
|
||||
dispdev.setDetected(screen_model);
|
||||
#endif
|
||||
|
||||
// I think this is not needed - redundant with ui.init
|
||||
@@ -862,6 +894,12 @@ int32_t Screen::runOnce()
|
||||
showingBootScreen = false;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_WELCOME_UNSET
|
||||
if (radioConfig.preferences.region == RegionCode_Unset) {
|
||||
setWelcomeFrames();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Process incoming commands.
|
||||
for (;;) {
|
||||
ScreenCmd cmd;
|
||||
@@ -975,6 +1013,20 @@ void Screen::setSSLFrames()
|
||||
}
|
||||
}
|
||||
|
||||
/* show a message that the SSL cert is being built
|
||||
* it is expected that this will be used during the boot phase */
|
||||
void Screen::setWelcomeFrames()
|
||||
{
|
||||
if (address_found) {
|
||||
// DEBUG_MSG("showing Welcome frames\n");
|
||||
ui.disableAllIndicators();
|
||||
|
||||
static FrameCallback welcomeFrames[] = {drawWelcomeScreen};
|
||||
ui.setFrames(welcomeFrames, 1);
|
||||
ui.update();
|
||||
}
|
||||
}
|
||||
|
||||
// restore our regular frame list
|
||||
void Screen::setFrames()
|
||||
{
|
||||
@@ -1366,7 +1418,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
}
|
||||
|
||||
auto mode = "";
|
||||
|
||||
|
||||
if (channels.getPrimary().modem_config == 0) {
|
||||
mode = "VLongSlow";
|
||||
} else if (channels.getPrimary().modem_config == 1) {
|
||||
@@ -1380,7 +1432,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
} else if (channels.getPrimary().modem_config == 5) {
|
||||
mode = "ShortSlow";
|
||||
} else if (channels.getPrimary().modem_config == 6) {
|
||||
mode = "ShortFast";
|
||||
mode = "ShortFast";
|
||||
} else {
|
||||
mode = "Custom";
|
||||
}
|
||||
@@ -1432,8 +1484,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
// Display Channel Utilization
|
||||
char chUtil[13];
|
||||
sprintf(chUtil, "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil),
|
||||
y + FONT_HEIGHT_SMALL * 1, chUtil);
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), y + FONT_HEIGHT_SMALL * 1, chUtil);
|
||||
|
||||
// Line 3
|
||||
if (radioConfig.preferences.gps_format != GpsCoordinateFormat_GpsFormatDMS) // if DMS then don't draw altitude
|
||||
@@ -1491,16 +1542,13 @@ int Screen::handleTextMessage(const MeshPacket *packet)
|
||||
int Screen::handleUIFrameEvent(const UIFrameEvent *event)
|
||||
{
|
||||
if (showingNormalScreen) {
|
||||
if (event->frameChanged)
|
||||
{
|
||||
if (event->frameChanged) {
|
||||
setFrames(); // Regen the list of screens (will show new text message)
|
||||
}
|
||||
else if (event->needRedraw)
|
||||
{
|
||||
} else if (event->needRedraw) {
|
||||
setFastFramerate();
|
||||
// TODO: We might also want switch to corresponding frame,
|
||||
// but we don't know the exact frame number.
|
||||
//ui.switchToFrame(0);
|
||||
// ui.switchToFrame(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -235,6 +235,8 @@ class Screen : public concurrency::OSThread
|
||||
/// Draws our SSL cert screen during boot (called from WebServer)
|
||||
void setSSLFrames();
|
||||
|
||||
void setWelcomeFrames();
|
||||
|
||||
protected:
|
||||
/// Updates the UI.
|
||||
//
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
#include "configuration.h"
|
||||
#include "DSRRouter.h"
|
||||
|
||||
/* when we receive any packet
|
||||
|
||||
- sniff and update tables (especially useful to find adjacent nodes). Update user, network and position info.
|
||||
- if we need to route() that packet, resend it to the next_hop based on our nodedb.
|
||||
- if it is broadcast or destined for our node, deliver locally
|
||||
- handle routereply/routeerror/routediscovery messages as described below
|
||||
- then free it
|
||||
|
||||
routeDiscovery
|
||||
|
||||
- if we've already passed through us (or is from us), then it ignore it
|
||||
- use the nodes already mentioned in the request to update our routing table
|
||||
- if they were looking for us, send back a routereply
|
||||
- if max_hops is zero and they weren't looking for us, drop (FIXME, send back error - I think not though?)
|
||||
- if we receive a discovery packet, we use it to populate next_hop (if needed) towards the requester (after decrementing max_hops)
|
||||
- if we receive a discovery packet, and we have a next_hop in our nodedb for that destination we send a (reliable) we send a route
|
||||
reply towards the requester
|
||||
|
||||
when sending any reliable packet
|
||||
|
||||
- if timeout doing retries, send a routeError (nak) message back towards the original requester. all nodes eavesdrop on that
|
||||
packet and update their route caches.
|
||||
|
||||
when we receive a routereply packet
|
||||
|
||||
- update next_hop on the node, if the new reply needs fewer hops than the existing one (we prefer shorter paths). fixme, someday
|
||||
use a better heuristic
|
||||
|
||||
when we receive a routeError packet
|
||||
|
||||
- delete the route for that failed recipient, restartRouteDiscovery()
|
||||
- if we receive routeerror in response to a discovery,
|
||||
- fixme, eventually keep caches of possible other routes.
|
||||
*/
|
||||
|
||||
ErrorCode DSRRouter::send(MeshPacket *p)
|
||||
{
|
||||
// We only consider multihop routing packets (i.e. those with dest set)
|
||||
if (p->decoded.dest) {
|
||||
// add an entry for this pending message
|
||||
auto pending = startRetransmission(p);
|
||||
// FIXME - when acks come in for this packet, we should _not_ delete the record unless the ack was from
|
||||
// the final dest. We need to keep that record around until FIXME
|
||||
// Also we should not retransmit multihop entries in that table at all
|
||||
|
||||
// If we have an entry in our routing tables, just send it, otherwise start a route discovery
|
||||
NodeNum nextHop = getNextHop(p->decoded.dest);
|
||||
if (nextHop) {
|
||||
sendNextHop(nextHop, p); // start a reliable single hop send
|
||||
} else {
|
||||
pending->wantRoute = true;
|
||||
|
||||
// start discovery, but only if we don't already a discovery in progress for that node number
|
||||
startDiscovery(p->decoded.dest);
|
||||
}
|
||||
|
||||
return ERRNO_OK;
|
||||
} else
|
||||
return ReliableRouter::send(p);
|
||||
}
|
||||
|
||||
void DSRRouter::sniffReceived(const MeshPacket *p, const Routing *c)
|
||||
{
|
||||
// Learn 0 hop routes by just hearing any adjacent nodes
|
||||
// But treat broadcasts carefully, because when flood broadcasts go out they keep the same original "from". So we want to
|
||||
// ignore rebroadcasts.
|
||||
// this will also add records for any ACKs we receive for our messages
|
||||
if (p->to != NODENUM_BROADCAST || p->hop_limit != HOP_RELIABLE) {
|
||||
addRoute(getFrom(p), getFrom(p), 0); // We are adjacent with zero hops
|
||||
}
|
||||
|
||||
if (c)
|
||||
switch (c->which_variant) {
|
||||
case Routing_route_request_tag:
|
||||
// Handle route discovery packets (will be a broadcast message)
|
||||
// FIXME - always start request with the senders nodenum
|
||||
if (weAreInRoute(c->route_request)) {
|
||||
DEBUG_MSG("Ignoring a route request that contains us\n");
|
||||
} else {
|
||||
updateRoutes(c->route_request,
|
||||
true); // Update our routing tables based on the route that came in so far on this request
|
||||
|
||||
if (p->decoded.dest == getNodeNum()) {
|
||||
// They were looking for us, send back a route reply (the sender address will be first in the list)
|
||||
sendRouteReply(c->route_request);
|
||||
} else {
|
||||
// They were looking for someone else, forward it along (as a zero hop broadcast)
|
||||
NodeNum nextHop = getNextHop(p->decoded.dest);
|
||||
if (nextHop) {
|
||||
// in our route cache, reply to the requester (the sender address will be first in the list)
|
||||
sendRouteReply(c->route_request, nextHop);
|
||||
} else {
|
||||
// Not in our route cache, rebroadcast on their behalf (after adding ourselves to the request route)
|
||||
resendRouteRequest(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Routing_route_reply_tag:
|
||||
updateRoutes(c->route_reply, false);
|
||||
|
||||
// FIXME, if any of our current pending packets were waiting for this route, send them (and leave them as regular
|
||||
// pending packets until ack arrives)
|
||||
// FIXME, if we don't get a route reply at all (or a route error), timeout and generate a routeerror TIMEOUT on our
|
||||
// own...
|
||||
break;
|
||||
case Routing_error_reason_tag:
|
||||
removeRoute(p->decoded.dest);
|
||||
|
||||
// FIXME: if any pending packets were waiting on this route, delete them
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// We simply ignore ACKs - because ReliableRouter will delete the pending packet for us
|
||||
|
||||
// Handle regular packets
|
||||
if (p->to == getNodeNum()) { // Destined for us (at least for this hop)
|
||||
|
||||
// We need to route this packet to some other node
|
||||
if (p->decoded.dest && p->decoded.dest != p->to) {
|
||||
// if we have a route out, resend the packet to the next hop, otherwise return RouteError no-route available
|
||||
|
||||
NodeNum nextHop = getNextHop(p->decoded.dest);
|
||||
if (nextHop) {
|
||||
sendNextHop(nextHop, p); // start a reliable single hop send
|
||||
} else {
|
||||
// We don't have a route out
|
||||
assert(p->decoded.source); // I think this is guaranteed by now
|
||||
|
||||
// FIXME - what if the current packet _is_ a route error packet?
|
||||
sendRouteError(p, Routing_Error_NO_ROUTE);
|
||||
}
|
||||
|
||||
// FIXME, stop local processing of this packet
|
||||
}
|
||||
|
||||
if (c) {
|
||||
// handle naks - convert them to route error packets
|
||||
// All naks are generated locally, because we failed resending the packet too many times
|
||||
PacketId nakId = c->error_reason ? p->decoded.request_id : 0;
|
||||
if (nakId) {
|
||||
auto pending = findPendingPacket(p->to, nakId);
|
||||
if (pending &&
|
||||
pending->packet->decoded.source) { // if source not set, this was not a multihop packet, just ignore
|
||||
removeRoute(pending->packet->decoded.dest); // We no longer have a route to the specified node
|
||||
|
||||
sendRouteError(p, Routing_Error_GOT_NAK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReliableRouter::sniffReceived(p, c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does our node appear in the specified route
|
||||
*/
|
||||
bool DSRRouter::weAreInRoute(const RouteDiscovery &route)
|
||||
{
|
||||
return true; // FIXME
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a DSR route, use that route to update our DB of possible routes
|
||||
*
|
||||
* Note: routes are always listed in the same order - from sender to receipient (i.e. route_replies also use this some order)
|
||||
*
|
||||
* @param isRequest is true if we are looking at a route request, else we are looking at a reply
|
||||
**/
|
||||
void DSRRouter::updateRoutes(const RouteDiscovery &route, bool isRequest)
|
||||
{
|
||||
DEBUG_MSG("FIXME not implemented updateRoutes\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* send back a route reply (the sender address will be first in the list)
|
||||
*/
|
||||
void DSRRouter::sendRouteReply(const RouteDiscovery &route, NodeNum toAppend)
|
||||
{
|
||||
DEBUG_MSG("FIXME not implemented sendRoute\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a nodenum return the next node we should forward to if we want to reach that node.
|
||||
*
|
||||
* @return 0 if no route found
|
||||
*/
|
||||
NodeNum DSRRouter::getNextHop(NodeNum dest)
|
||||
{
|
||||
DEBUG_MSG("FIXME not implemented getNextHop\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Not in our route cache, rebroadcast on their behalf (after adding ourselves to the request route)
|
||||
*
|
||||
* We will bump down hop_limit in this call.
|
||||
*/
|
||||
void DSRRouter::resendRouteRequest(const MeshPacket *p)
|
||||
{
|
||||
DEBUG_MSG("FIXME not implemented resendRoute\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Record that forwarder can reach dest for us, but they will need numHops to get there.
|
||||
* If our routing tables already have something that can reach that node in fewer hops we will keep the existing route
|
||||
* instead.
|
||||
*/
|
||||
void DSRRouter::addRoute(NodeNum dest, NodeNum forwarder, uint8_t numHops)
|
||||
{
|
||||
DEBUG_MSG("FIXME not implemented addRoute\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Record that we no longer have a route to the dest
|
||||
*/
|
||||
void DSRRouter::removeRoute(NodeNum dest)
|
||||
{
|
||||
DEBUG_MSG("FIXME not implemented removeRoute\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward the specified packet to the specified node
|
||||
*/
|
||||
void DSRRouter::sendNextHop(NodeNum n, const MeshPacket *p)
|
||||
{
|
||||
DEBUG_MSG("FIXME not implemented sendNextHop\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a route error packet towards whoever originally sent this message
|
||||
*/
|
||||
void DSRRouter::sendRouteError(const MeshPacket *p, Routing_Error err)
|
||||
{
|
||||
DEBUG_MSG("FIXME not implemented sendRouteError\n");
|
||||
}
|
||||
|
||||
/** make a copy of p, start discovery, but only if we don't
|
||||
* already a discovery in progress for that node number. Caller has already scheduled this message for retransmission
|
||||
* when the discovery is complete.
|
||||
*/
|
||||
void DSRRouter::startDiscovery(NodeNum dest)
|
||||
{
|
||||
DEBUG_MSG("FIXME not implemented startDiscovery\n");
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
#include "ReliableRouter.h"
|
||||
|
||||
class DSRRouter : public ReliableRouter
|
||||
{
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to
|
||||
* update routing tables etc... based on what we overhear (even for messages not destined to our node)
|
||||
*/
|
||||
virtual void sniffReceived(const MeshPacket *p, const Routing *c) override;
|
||||
|
||||
/**
|
||||
* Send a packet on a suitable interface. This routine will
|
||||
* later free() the packet to pool. This routine is not allowed to stall.
|
||||
* If the txmit queue is full it might return an error
|
||||
*/
|
||||
virtual ErrorCode send(MeshPacket *p) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Does our node appear in the specified route
|
||||
*/
|
||||
bool weAreInRoute(const RouteDiscovery &route);
|
||||
|
||||
/**
|
||||
* Given a DSR route, use that route to update our DB of possible routes
|
||||
*
|
||||
* Note: routes are always listed in the same order - from sender to receipient (i.e. route_replies also use this some order)
|
||||
*
|
||||
* @param isRequest is true if we are looking at a route request, else we are looking at a reply
|
||||
**/
|
||||
void updateRoutes(const RouteDiscovery &route, bool isRequest);
|
||||
|
||||
/**
|
||||
* send back a route reply (the sender address will be first in the list)
|
||||
*/
|
||||
void sendRouteReply(const RouteDiscovery &route, NodeNum toAppend = 0);
|
||||
|
||||
/**
|
||||
* Given a nodenum return the next node we should forward to if we want to reach that node.
|
||||
*
|
||||
* @return 0 if no route found
|
||||
*/
|
||||
NodeNum getNextHop(NodeNum dest);
|
||||
|
||||
/** Not in our route cache, rebroadcast on their behalf (after adding ourselves to the request route)
|
||||
*
|
||||
* We will bump down hop_limit in this call.
|
||||
*/
|
||||
void resendRouteRequest(const MeshPacket *p);
|
||||
|
||||
/**
|
||||
* Record that forwarder can reach dest for us, but they will need numHops to get there.
|
||||
* If our routing tables already have something that can reach that node in fewer hops we will keep the existing route
|
||||
* instead.
|
||||
*/
|
||||
void addRoute(NodeNum dest, NodeNum forwarder, uint8_t numHops);
|
||||
|
||||
/**
|
||||
* Record that we no longer have a route to the dest
|
||||
*/
|
||||
void removeRoute(NodeNum dest);
|
||||
|
||||
/**
|
||||
* Forward the specified packet to the specified node
|
||||
*/
|
||||
void sendNextHop(NodeNum n, const MeshPacket *p);
|
||||
|
||||
/**
|
||||
* Send a route error packet towards whoever originally sent this message
|
||||
*/
|
||||
void sendRouteError(const MeshPacket *p, Routing_Error err);
|
||||
|
||||
/** make a copy of p, start discovery, but only if we don't
|
||||
* already a discovery in progress for that node number. Caller has already scheduled this message for retransmission
|
||||
* when the discovery is complete.
|
||||
*/
|
||||
void startDiscovery(NodeNum dest);
|
||||
};
|
||||
@@ -141,12 +141,10 @@ extern NodeDB nodeDB;
|
||||
# prefs.position_broadcast_secs = FIXME possibly broadcast only once an hr
|
||||
prefs.wait_bluetooth_secs = 1 # Don't stay in bluetooth mode
|
||||
prefs.mesh_sds_timeout_secs = never
|
||||
prefs.phone_sds_timeout_sec = never
|
||||
# try to stay in light sleep one full day, then briefly wake and sleep again
|
||||
|
||||
prefs.ls_secs = oneday
|
||||
|
||||
prefs.send_owner_interval = 2 # Send an owner packet every other network ping
|
||||
prefs.position_broadcast_secs = 12 hours # send either position or owner every 12hrs
|
||||
|
||||
# get a new GPS position once per day
|
||||
@@ -166,7 +164,6 @@ extern NodeDB nodeDB;
|
||||
#define PREF_GET(name, defaultVal) \
|
||||
inline uint32_t getPref_##name() { return radioConfig.preferences.name ? radioConfig.preferences.name : (defaultVal); }
|
||||
|
||||
PREF_GET(send_owner_interval, IF_ROUTER(2, 4))
|
||||
PREF_GET(position_broadcast_secs, IF_ROUTER(12 * 60 * 60, 15 * 60))
|
||||
// Defaulting Telemetry to the same as position interval for now
|
||||
PREF_GET(telemetry_module_device_update_interval, IF_ROUTER(12 * 60 * 60, 15 * 60))
|
||||
@@ -178,7 +175,6 @@ PREF_GET(wait_bluetooth_secs, IF_ROUTER(1, 60))
|
||||
|
||||
PREF_GET(screen_on_secs, 60)
|
||||
PREF_GET(mesh_sds_timeout_secs, IF_ROUTER(NODE_DELAY_FOREVER, 2 * 60 * 60))
|
||||
PREF_GET(phone_sds_timeout_sec, IF_ROUTER(NODE_DELAY_FOREVER, 2 * 60 * 60))
|
||||
PREF_GET(sds_secs, 365 * 24 * 60 * 60)
|
||||
|
||||
// We default to sleeping (with bluetooth off for 5 minutes at a time). This seems to be a good tradeoff between
|
||||
|
||||
@@ -48,7 +48,7 @@ void PhoneAPI::close()
|
||||
if (state != STATE_SEND_NOTHING) {
|
||||
state = STATE_SEND_NOTHING;
|
||||
|
||||
unobserve();
|
||||
unobserve(&service.fromNumChanged);
|
||||
releasePhonePacket(); // Don't leak phone packets on shutdown
|
||||
|
||||
onConnectionChanged(false);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "configuration.h"
|
||||
#include "RadioLibInterface.h"
|
||||
#include "MeshTypes.h"
|
||||
#include "NodeDB.h"
|
||||
#include "SPILock.h"
|
||||
#include "configuration.h"
|
||||
#include "error.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
#include <pb_decode.h>
|
||||
@@ -93,8 +93,15 @@ bool RadioLibInterface::canSendImmediately()
|
||||
/// bluetooth comms code. If the txmit queue is empty it might return an error
|
||||
ErrorCode RadioLibInterface::send(MeshPacket *p)
|
||||
{
|
||||
if (disabled || radioConfig.preferences.is_lora_tx_disabled) {
|
||||
DEBUG_MSG("send - lora_tx_disabled\n");
|
||||
if (radioConfig.preferences.region != RegionCode_Unset) {
|
||||
if (disabled || radioConfig.preferences.is_lora_tx_disabled) {
|
||||
DEBUG_MSG("send - lora_tx_disabled\n");
|
||||
packetPool.release(p);
|
||||
return ERRNO_DISABLED;
|
||||
}
|
||||
|
||||
} else {
|
||||
DEBUG_MSG("send - lora_tx_disabled because RegionCode_Unset\n");
|
||||
packetPool.release(p);
|
||||
return ERRNO_DISABLED;
|
||||
}
|
||||
@@ -115,9 +122,9 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
|
||||
// in response to a packet we just received. So we want to make sure the other side has had a chance to reconfigure its radio
|
||||
|
||||
/* We assume if rx_snr = 0 and rx_rssi = 0, the packet was not generated locally.
|
||||
* This assumption is valid because of the offset generated by the radio to account for the noise
|
||||
* floor.
|
||||
*/
|
||||
* This assumption is valid because of the offset generated by the radio to account for the noise
|
||||
* floor.
|
||||
*/
|
||||
if (p->rx_snr == 0 && p->rx_rssi == 0) {
|
||||
startTransmitTimer(true);
|
||||
} else {
|
||||
@@ -125,7 +132,6 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
|
||||
DEBUG_MSG("rx_snr found. hop_limit:%d rx_snr:%f\n", p->hop_limit, p->rx_snr);
|
||||
startTransmitTimerSNR(p->rx_snr);
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
#else
|
||||
@@ -311,7 +317,7 @@ void RadioLibInterface::handleReceiveInterrupt()
|
||||
|
||||
printPacket("Lora RX", mp);
|
||||
|
||||
//xmitMsec = getPacketTime(mp);
|
||||
// xmitMsec = getPacketTime(mp);
|
||||
airTime->logAirtime(RX_LOG, xmitMsec);
|
||||
|
||||
deliverToReceiver(mp);
|
||||
@@ -334,7 +340,7 @@ void RadioLibInterface::startSend(MeshPacket *txp)
|
||||
size_t numbytes = beginSending(txp);
|
||||
|
||||
int res = iface->startTransmit(radiobuf, numbytes);
|
||||
if(res != ERR_NONE) {
|
||||
if (res != ERR_NONE) {
|
||||
RECORD_CRITICALERROR(CriticalErrorCode_RadioSpiBug);
|
||||
|
||||
// This send failed, but make sure to 'complete' it properly
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#include "configuration.h"
|
||||
#include "Router.h"
|
||||
#include "Channels.h"
|
||||
#include "CryptoEngine.h"
|
||||
#include "NodeDB.h"
|
||||
#include "RTC.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
#include "modules/RoutingModule.h"
|
||||
extern "C" {
|
||||
#include "mesh/compression/unishox2.h"
|
||||
}
|
||||
|
||||
#if defined(HAS_WIFI) || defined(PORTDUINO)
|
||||
#include "mqtt/MQTT.h"
|
||||
@@ -210,29 +213,27 @@ ErrorCode Router::send(MeshPacket *p)
|
||||
if (p->which_payloadVariant == MeshPacket_decoded_tag) {
|
||||
ChannelIndex chIndex = p->channel; // keep as a local because we are about to change it
|
||||
|
||||
|
||||
|
||||
#if defined(HAS_WIFI) || defined(PORTDUINO)
|
||||
//check if we should send decrypted packets to mqtt
|
||||
// check if we should send decrypted packets to mqtt
|
||||
|
||||
//truth table:
|
||||
// truth table:
|
||||
/* mqtt_server mqtt_encryption_enabled should_encrypt
|
||||
* not set 0 1
|
||||
* not set 1 1
|
||||
* set 0 0
|
||||
* set 1 1
|
||||
*
|
||||
*
|
||||
* => so we only decrypt mqtt if they have a custom mqtt server AND mqtt_encryption_enabled is FALSE
|
||||
*/
|
||||
*/
|
||||
|
||||
bool shouldActuallyEncrypt = true;
|
||||
if (*radioConfig.preferences.mqtt_server && !radioConfig.preferences.mqtt_encryption_enabled) {
|
||||
shouldActuallyEncrypt = false;
|
||||
}
|
||||
|
||||
|
||||
DEBUG_MSG("Should encrypt MQTT?: %d\n", shouldActuallyEncrypt);
|
||||
|
||||
//the packet is currently in a decrypted state. send it now if they want decrypted packets
|
||||
// the packet is currently in a decrypted state. send it now if they want decrypted packets
|
||||
if (mqtt && !shouldActuallyEncrypt)
|
||||
mqtt->onSend(*p, chIndex);
|
||||
#endif
|
||||
@@ -244,8 +245,8 @@ ErrorCode Router::send(MeshPacket *p)
|
||||
}
|
||||
|
||||
#if defined(HAS_WIFI) || defined(PORTDUINO)
|
||||
//the packet is now encrypted.
|
||||
//check if we should send encrypted packets to mqtt
|
||||
// the packet is now encrypted.
|
||||
// check if we should send encrypted packets to mqtt
|
||||
if (mqtt && shouldActuallyEncrypt)
|
||||
mqtt->onSend(*p, chIndex);
|
||||
#endif
|
||||
@@ -276,7 +277,7 @@ bool perhapsDecode(MeshPacket *p)
|
||||
if (p->which_payloadVariant == MeshPacket_decoded_tag)
|
||||
return true; // If packet was already decoded just return
|
||||
|
||||
//assert(p->which_payloadVariant == MeshPacket_encrypted_tag);
|
||||
// assert(p->which_payloadVariant == MeshPacket_encrypted_tag);
|
||||
|
||||
// Try to find a channel that works with this hash
|
||||
for (ChannelIndex chIndex = 0; chIndex < channels.getNumChannels(); chIndex++) {
|
||||
@@ -302,6 +303,14 @@ bool perhapsDecode(MeshPacket *p)
|
||||
// parsing was successful
|
||||
p->which_payloadVariant = MeshPacket_decoded_tag; // change type to decoded
|
||||
p->channel = chIndex; // change to store the index instead of the hash
|
||||
|
||||
|
||||
// Decompress if needed. jm
|
||||
if (p->decoded.which_payloadVariant == Data_payload_compressed_tag) {
|
||||
// Decompress the file
|
||||
}
|
||||
|
||||
|
||||
printPacket("decoded message", p);
|
||||
return true;
|
||||
}
|
||||
@@ -320,10 +329,55 @@ Routing_Error perhapsEncode(MeshPacket *p)
|
||||
if (p->which_payloadVariant == MeshPacket_decoded_tag) {
|
||||
static uint8_t bytes[MAX_RHPACKETLEN]; // we have to use a scratch buffer because a union
|
||||
|
||||
// printPacket("pre encrypt", p); // portnum valid here
|
||||
|
||||
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), Data_fields, &p->decoded);
|
||||
|
||||
// Only allow encryption on the text message app.
|
||||
// TODO: Allow modules to opt into compression.
|
||||
if (p->decoded.portnum == PortNum_TEXT_MESSAGE_APP) {
|
||||
|
||||
char original_payload[Constants_DATA_PAYLOAD_LEN];
|
||||
memcpy(original_payload, p->decoded.payload.bytes, p->decoded.payload.size);
|
||||
|
||||
char compressed_out[Constants_DATA_PAYLOAD_LEN] = {0};
|
||||
|
||||
int compressed_len = unishox2_compress_simple(original_payload, p->decoded.payload.size, compressed_out);
|
||||
|
||||
Serial.print("Original length - ");
|
||||
Serial.println(p->decoded.payload.size);
|
||||
|
||||
Serial.print("Compressed length - ");
|
||||
Serial.println(compressed_len);
|
||||
// Serial.println(compressed_out);
|
||||
|
||||
// If the compressed length is greater than or equal to the original size, don't use the compressed form
|
||||
if (compressed_len >= p->decoded.payload.size) {
|
||||
|
||||
DEBUG_MSG("Not compressing message. Not enough benefit from doing so.\n");
|
||||
// Set the uncompressed payload varient anyway. Shouldn't hurt?
|
||||
p->decoded.which_payloadVariant = Data_payload_tag;
|
||||
|
||||
// Otherwise we use the compressor
|
||||
} else {
|
||||
DEBUG_MSG("Compressing message.\n");
|
||||
// Copy the compressed data into the meshpacket
|
||||
//p->decoded.payload_compressed.size = compressed_len;
|
||||
//memcpy(p->decoded.payload_compressed.bytes, compressed_out, compressed_len);
|
||||
|
||||
//p->decoded.which_payloadVariant = Data_payload_compressed_tag;
|
||||
}
|
||||
|
||||
if (1) {
|
||||
char decompressed_out[Constants_DATA_PAYLOAD_LEN] = {};
|
||||
int decompressed_len;
|
||||
|
||||
decompressed_len = unishox2_decompress_simple(compressed_out, compressed_len, decompressed_out);
|
||||
|
||||
Serial.print("Decompressed length - ");
|
||||
Serial.println(decompressed_len);
|
||||
Serial.println(decompressed_out);
|
||||
}
|
||||
}
|
||||
|
||||
if (numbytes > MAX_RHPACKETLEN)
|
||||
return Routing_Error_TOO_LARGE;
|
||||
|
||||
|
||||
1342
src/mesh/compression/unishox2.c
Normal file
1342
src/mesh/compression/unishox2.c
Normal file
File diff suppressed because it is too large
Load Diff
278
src/mesh/compression/unishox2.h
Normal file
278
src/mesh/compression/unishox2.h
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Siara Logics (cc)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Arundale Ramanathan
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file unishox2.h
|
||||
* @author Arundale Ramanathan, James Z. M. Gao
|
||||
* @brief API for Unishox2 Compression and Decompression
|
||||
*
|
||||
* This file describes each function of the Unishox2 API \n
|
||||
* For finding out how this API can be used in your program, \n
|
||||
* please see test_unishox2.c.
|
||||
*/
|
||||
|
||||
#ifndef unishox2
|
||||
#define unishox2
|
||||
|
||||
#define UNISHOX_VERSION "2.0" ///< Unicode spec version
|
||||
|
||||
/**
|
||||
* Macro switch to enable/disable output buffer length parameter in low level api \n
|
||||
* Disabled by default \n
|
||||
* When this macro is defined, the all the API functions \n
|
||||
* except the simple API functions accept an additional parameter olen \n
|
||||
* that enables the developer to pass the size of the output buffer provided \n
|
||||
* so that the api function may not write beyond that length. \n
|
||||
* This can be disabled if the developer knows that the buffer provided is sufficient enough \n
|
||||
* so no additional parameter is passed and the program is faster since additional check \n
|
||||
* for output length is not performed at each step \n
|
||||
* The simple api, i.e. unishox2_(de)compress_simple will always omit the buffer length
|
||||
*/
|
||||
#ifndef UNISHOX_API_WITH_OUTPUT_LEN
|
||||
# define UNISHOX_API_WITH_OUTPUT_LEN 0
|
||||
#endif
|
||||
|
||||
/// Upto 8 bits of initial magic bit sequence can be included. Bit count can be specified with UNISHOX_MAGIC_BIT_LEN
|
||||
#ifndef UNISHOX_MAGIC_BITS
|
||||
# define UNISHOX_MAGIC_BITS 0xFF
|
||||
#endif
|
||||
|
||||
/// Desired length of Magic bits defined by UNISHOX_MAGIC_BITS
|
||||
#ifdef UNISHOX_MAGIC_BIT_LEN
|
||||
# if UNISHOX_MAGIC_BIT_LEN < 0 || 9 <= UNISHOX_MAGIC_BIT_LEN
|
||||
# error "UNISHOX_MAGIC_BIT_LEN need between [0, 8)"
|
||||
# endif
|
||||
#else
|
||||
# define UNISHOX_MAGIC_BIT_LEN 1
|
||||
#endif
|
||||
|
||||
//enum {USX_ALPHA = 0, USX_SYM, USX_NUM, USX_DICT, USX_DELTA};
|
||||
|
||||
/// Default Horizontal codes. When composition of text is know beforehand, the other hcodes in this section can be used to achieve more compression.
|
||||
#define USX_HCODES_DFLT (const unsigned char[]) {0x00, 0x40, 0x80, 0xC0, 0xE0}
|
||||
/// Length of each default hcode
|
||||
#define USX_HCODE_LENS_DFLT (const unsigned char[]) {2, 2, 2, 3, 3}
|
||||
|
||||
/// Horizontal codes preset for English Alphabet content only
|
||||
#define USX_HCODES_ALPHA_ONLY (const unsigned char[]) {0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
/// Length of each Alpha only hcode
|
||||
#define USX_HCODE_LENS_ALPHA_ONLY (const unsigned char[]) {0, 0, 0, 0, 0}
|
||||
|
||||
/// Horizontal codes preset for Alpha Numeric content only
|
||||
#define USX_HCODES_ALPHA_NUM_ONLY (const unsigned char[]) {0x00, 0x00, 0x80, 0x00, 0x00}
|
||||
/// Length of each Alpha numeric hcode
|
||||
#define USX_HCODE_LENS_ALPHA_NUM_ONLY (const unsigned char[]) {1, 0, 1, 0, 0}
|
||||
|
||||
/// Horizontal codes preset for Alpha Numeric and Symbol content only
|
||||
#define USX_HCODES_ALPHA_NUM_SYM_ONLY (const unsigned char[]) {0x00, 0x80, 0xC0, 0x00, 0x00}
|
||||
/// Length of each Alpha numeric and symbol hcodes
|
||||
#define USX_HCODE_LENS_ALPHA_NUM_SYM_ONLY (const unsigned char[]) {1, 2, 2, 0, 0}
|
||||
|
||||
/// Horizontal codes preset favouring Alphabet content
|
||||
#define USX_HCODES_FAVOR_ALPHA (const unsigned char[]) {0x00, 0x80, 0xA0, 0xC0, 0xE0}
|
||||
/// Length of each hcode favouring Alpha content
|
||||
#define USX_HCODE_LENS_FAVOR_ALPHA (const unsigned char[]) {1, 3, 3, 3, 3}
|
||||
|
||||
/// Horizontal codes preset favouring repeating sequences
|
||||
#define USX_HCODES_FAVOR_DICT (const unsigned char[]) {0x00, 0x40, 0xC0, 0x80, 0xE0}
|
||||
/// Length of each hcode favouring repeating sequences
|
||||
#define USX_HCODE_LENS_FAVOR_DICT (const unsigned char[]) {2, 2, 3, 2, 3}
|
||||
|
||||
/// Horizontal codes preset favouring symbols
|
||||
#define USX_HCODES_FAVOR_SYM (const unsigned char[]) {0x80, 0x00, 0xA0, 0xC0, 0xE0}
|
||||
/// Length of each hcode favouring symbols
|
||||
#define USX_HCODE_LENS_FAVOR_SYM (const unsigned char[]) {3, 1, 3, 3, 3}
|
||||
|
||||
//#define USX_HCODES_FAVOR_UMLAUT {0x00, 0x40, 0xE0, 0xC0, 0x80}
|
||||
//#define USX_HCODE_LENS_FAVOR_UMLAUT {2, 2, 3, 3, 2}
|
||||
|
||||
/// Horizontal codes preset favouring umlaut letters
|
||||
#define USX_HCODES_FAVOR_UMLAUT (const unsigned char[]) {0x80, 0xA0, 0xC0, 0xE0, 0x00}
|
||||
/// Length of each hcode favouring umlaut letters
|
||||
#define USX_HCODE_LENS_FAVOR_UMLAUT (const unsigned char[]) {3, 3, 3, 3, 1}
|
||||
|
||||
/// Horizontal codes preset for no repeating sequences
|
||||
#define USX_HCODES_NO_DICT (const unsigned char[]) {0x00, 0x40, 0x80, 0x00, 0xC0}
|
||||
/// Length of each hcode for no repeating sequences
|
||||
#define USX_HCODE_LENS_NO_DICT (const unsigned char[]) {2, 2, 2, 0, 2}
|
||||
|
||||
/// Horizontal codes preset for no Unicode characters
|
||||
#define USX_HCODES_NO_UNI (const unsigned char[]) {0x00, 0x40, 0x80, 0xC0, 0x00}
|
||||
/// Length of each hcode for no Unicode characters
|
||||
#define USX_HCODE_LENS_NO_UNI (const unsigned char[]) {2, 2, 2, 2, 0}
|
||||
|
||||
/// Default frequently occuring sequences. When composition of text is know beforehand, the other sequences in this section can be used to achieve more compression.
|
||||
#define USX_FREQ_SEQ_DFLT (const char *[]) {"\": \"", "\": ", "</", "=\"", "\":\"", "://"}
|
||||
/// Frequently occuring sequences in text content
|
||||
#define USX_FREQ_SEQ_TXT (const char *[]) {" the ", " and ", "tion", " with", "ing", "ment"}
|
||||
/// Frequently occuring sequences in URL content
|
||||
#define USX_FREQ_SEQ_URL (const char *[]) {"https://", "www.", ".com", "http://", ".org", ".net"}
|
||||
/// Frequently occuring sequences in JSON content
|
||||
#define USX_FREQ_SEQ_JSON (const char *[]) {"\": \"", "\": ", "\",", "}}}", "\":\"", "}}"}
|
||||
/// Frequently occuring sequences in HTML content
|
||||
#define USX_FREQ_SEQ_HTML (const char *[]) {"</", "=\"", "div", "href", "class", "<p>"}
|
||||
/// Frequently occuring sequences in XML content
|
||||
#define USX_FREQ_SEQ_XML (const char *[]) {"</", "=\"", "\">", "<?xml version=\"1.0\"", "xmlns:", "://"}
|
||||
|
||||
/// Commonly occuring templates (ISO Date/Time, ISO Date, US Phone number, ISO Time, Unused)
|
||||
#define USX_TEMPLATES (const char *[]) {"tfff-of-tfTtf:rf:rf.fffZ", "tfff-of-tf", "(fff) fff-ffff", "tf:rf:rf", 0}
|
||||
|
||||
/// Default preset parameter set. When composition of text is know beforehand, the other parameter sets in this section can be used to achieve more compression.
|
||||
#define USX_PSET_DFLT USX_HCODES_DFLT, USX_HCODE_LENS_DFLT, USX_FREQ_SEQ_DFLT, USX_TEMPLATES
|
||||
/// Preset parameter set for English Alphabet only content
|
||||
#define USX_PSET_ALPHA_ONLY USX_HCODES_ALPHA_ONLY, USX_HCODE_LENS_ALPHA_ONLY, USX_FREQ_SEQ_TXT, USX_TEMPLATES
|
||||
/// Preset parameter set for Alpha numeric content
|
||||
#define USX_PSET_ALPHA_NUM_ONLY USX_HCODES_ALPHA_NUM_ONLY, USX_HCODE_LENS_ALPHA_NUM_ONLY, USX_FREQ_SEQ_TXT, USX_TEMPLATES
|
||||
/// Preset parameter set for Alpha numeric and symbol content
|
||||
#define USX_PSET_ALPHA_NUM_SYM_ONLY USX_HCODES_ALPHA_NUM_SYM_ONLY, USX_HCODE_LENS_ALPHA_NUM_SYM_ONLY, USX_FREQ_SEQ_DFLT, USX_TEMPLATES
|
||||
/// Preset parameter set for Alpha numeric symbol content having predominantly text
|
||||
#define USX_PSET_ALPHA_NUM_SYM_ONLY_TXT USX_HCODES_ALPHA_NUM_SYM_ONLY, USX_HCODE_LENS_ALPHA_NUM_SYM_ONLY, USX_FREQ_SEQ_DFLT, USX_TEMPLATES
|
||||
/// Preset parameter set favouring Alphabet content
|
||||
#define USX_PSET_FAVOR_ALPHA USX_HCODES_FAVOR_ALPHA, USX_HCODE_LENS_FAVOR_ALPHA, USX_FREQ_SEQ_TXT, USX_TEMPLATES
|
||||
/// Preset parameter set favouring repeating sequences
|
||||
#define USX_PSET_FAVOR_DICT USX_HCODES_FAVOR_DICT, USX_HCODE_LENS_FAVOR_DICT, USX_FREQ_SEQ_DFLT, USX_TEMPLATES
|
||||
/// Preset parameter set favouring symbols
|
||||
#define USX_PSET_FAVOR_SYM USX_HCODES_FAVOR_SYM, USX_HCODE_LENS_FAVOR_SYM, USX_FREQ_SEQ_DFLT, USX_TEMPLATES
|
||||
/// Preset parameter set favouring unlaut letters
|
||||
#define USX_PSET_FAVOR_UMLAUT USX_HCODES_FAVOR_UMLAUT, USX_HCODE_LENS_FAVOR_UMLAUT, USX_FREQ_SEQ_DFLT, USX_TEMPLATES
|
||||
/// Preset parameter set for when there are no repeating sequences
|
||||
#define USX_PSET_NO_DICT USX_HCODES_NO_DICT, USX_HCODE_LENS_NO_DICT, USX_FREQ_SEQ_DFLT, USX_TEMPLATES
|
||||
/// Preset parameter set for when there are no unicode symbols
|
||||
#define USX_PSET_NO_UNI USX_HCODES_NO_UNI, USX_HCODE_LENS_NO_UNI, USX_FREQ_SEQ_DFLT, USX_TEMPLATES
|
||||
/// Preset parameter set for when there are no unicode symbols favouring text
|
||||
#define USX_PSET_NO_UNI_FAVOR_TEXT USX_HCODES_NO_UNI, USX_HCODE_LENS_NO_UNI, USX_FREQ_SEQ_TXT, USX_TEMPLATES
|
||||
/// Preset parameter set favouring URL content
|
||||
#define USX_PSET_URL USX_HCODES_DFLT, USX_HCODE_LENS_DFLT, USX_FREQ_SEQ_URL, USX_TEMPLATES
|
||||
/// Preset parameter set favouring JSON content
|
||||
#define USX_PSET_JSON USX_HCODES_DFLT, USX_HCODE_LENS_DFLT, USX_FREQ_SEQ_JSON, USX_TEMPLATES
|
||||
/// Preset parameter set favouring JSON content having no Unicode symbols
|
||||
#define USX_PSET_JSON_NO_UNI USX_HCODES_NO_UNI, USX_HCODE_LENS_NO_UNI, USX_FREQ_SEQ_JSON, USX_TEMPLATES
|
||||
/// Preset parameter set favouring XML content
|
||||
#define USX_PSET_XML USX_HCODES_DFLT, USX_HCODE_LENS_DFLT, USX_FREQ_SEQ_XML, USX_TEMPLATES
|
||||
/// Preset parameter set favouring HTML content
|
||||
#define USX_PSET_HTML USX_HCODES_DFLT, USX_HCODE_LENS_DFLT, USX_FREQ_SEQ_HTML, USX_TEMPLATES
|
||||
|
||||
/**
|
||||
* This structure is used when a string array needs to be compressed.
|
||||
* This is passed as a parameter to the unishox2_decompress_lines() function
|
||||
*/
|
||||
struct us_lnk_lst {
|
||||
char *data;
|
||||
struct us_lnk_lst *previous;
|
||||
};
|
||||
|
||||
/**
|
||||
* This macro is for internal use, but builds upon the macro UNISHOX_API_WITH_OUTPUT_LEN
|
||||
* When the macro UNISHOX_API_WITH_OUTPUT_LEN is defined, the all the API functions
|
||||
* except the simple API functions accept an additional parameter olen
|
||||
* that enables the developer to pass the size of the output buffer provided
|
||||
* so that the api function may not write beyond that length.
|
||||
* This can be disabled if the developer knows that the buffer provided is sufficient enough
|
||||
* so no additional parameter is passed and the program is faster since additional check
|
||||
* for output length is not performed at each step
|
||||
*/
|
||||
#if defined(UNISHOX_API_WITH_OUTPUT_LEN) && UNISHOX_API_WITH_OUTPUT_LEN != 0
|
||||
# define UNISHOX_API_OUT_AND_LEN(out, olen) out, olen
|
||||
#else
|
||||
# define UNISHOX_API_OUT_AND_LEN(out, olen) out
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Simple API for compressing a string
|
||||
* @param[in] in Input ASCII / UTF-8 string
|
||||
* @param[in] len length in bytes
|
||||
* @param[out] out output buffer - should be large enough to hold compressed output
|
||||
*/
|
||||
extern int unishox2_compress_simple(const char *in, int len, char *out);
|
||||
/**
|
||||
* Simple API for decompressing a string
|
||||
* @param[in] in Input compressed bytes (output of unishox2_compress functions)
|
||||
* @param[in] len length of 'in' in bytes
|
||||
* @param[out] out output buffer for ASCII / UTF-8 string - should be large enough
|
||||
*/
|
||||
extern int unishox2_decompress_simple(const char *in, int len, char *out);
|
||||
/**
|
||||
* Comprehensive API for compressing a string
|
||||
*
|
||||
* Presets are available for the last four parameters so they can be passed as single parameter. \n
|
||||
* See USX_PSET_* macros. Example call: \n
|
||||
* unishox2_compress(in, len, out, olen, USX_PSET_ALPHA_ONLY);
|
||||
*
|
||||
* @param[in] in Input ASCII / UTF-8 string
|
||||
* @param[in] len length in bytes
|
||||
* @param[out] out output buffer - should be large enough to hold compressed output
|
||||
* @param[in] olen length of 'out' buffer in bytes. Can be omitted if sufficient buffer is provided
|
||||
* @param[in] usx_hcodes Horizontal codes (array of bytes). See macro section for samples.
|
||||
* @param[in] usx_hcode_lens Length of each element in usx_hcodes array
|
||||
* @param[in] usx_freq_seq Frequently occuring sequences. See USX_FREQ_SEQ_* macros for samples
|
||||
* @param[in] usx_templates Templates of frequently occuring patterns. See USX_TEMPLATES macro.
|
||||
*/
|
||||
extern int unishox2_compress(const char *in, int len, UNISHOX_API_OUT_AND_LEN(char *out, int olen),
|
||||
const unsigned char usx_hcodes[], const unsigned char usx_hcode_lens[],
|
||||
const char *usx_freq_seq[], const char *usx_templates[]);
|
||||
/**
|
||||
* Comprehensive API for de-compressing a string
|
||||
*
|
||||
* Presets are available for the last four parameters so they can be passed as single parameter. \n
|
||||
* See USX_PSET_* macros. Example call: \n
|
||||
* unishox2_decompress(in, len, out, olen, USX_PSET_ALPHA_ONLY);
|
||||
*
|
||||
* @param[in] in Input compressed bytes (output of unishox2_compress functions)
|
||||
* @param[in] len length of 'in' in bytes
|
||||
* @param[out] out output buffer - should be large enough to hold de-compressed output
|
||||
* @param[in] olen length of 'out' buffer in bytes. Can be omitted if sufficient buffer is provided
|
||||
* @param[in] usx_hcodes Horizontal codes (array of bytes). See macro section for samples.
|
||||
* @param[in] usx_hcode_lens Length of each element in usx_hcodes array
|
||||
* @param[in] usx_freq_seq Frequently occuring sequences. See USX_FREQ_SEQ_* macros for samples
|
||||
* @param[in] usx_templates Templates of frequently occuring patterns. See USX_TEMPLATES macro.
|
||||
*/
|
||||
extern int unishox2_decompress(const char *in, int len, UNISHOX_API_OUT_AND_LEN(char *out, int olen),
|
||||
const unsigned char usx_hcodes[], const unsigned char usx_hcode_lens[],
|
||||
const char *usx_freq_seq[], const char *usx_templates[]);
|
||||
/**
|
||||
* More Comprehensive API for compressing array of strings
|
||||
*
|
||||
* See unishox2_compress() function for parameter definitions. \n
|
||||
* This function takes an additional parameter, i.e. 'prev_lines' - the usx_lnk_lst structure \n
|
||||
* See -g parameter in test_unishox2.c to find out how this can be used. \n
|
||||
* This function is used when an array of strings need to be compressed \n
|
||||
* and stored in a compressed array of bytes for use as a constant in other programs \n
|
||||
* where each element of the array can be decompressed and used at runtime.
|
||||
*/
|
||||
extern int unishox2_compress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(char *out, int olen),
|
||||
const unsigned char usx_hcodes[], const unsigned char usx_hcode_lens[],
|
||||
const char *usx_freq_seq[], const char *usx_templates[],
|
||||
struct us_lnk_lst *prev_lines);
|
||||
/**
|
||||
* More Comprehensive API for de-compressing array of strings \n
|
||||
* This function is not be used in conjuction with unishox2_compress_lines()
|
||||
*
|
||||
* See unishox2_decompress() function for parameter definitions. \n
|
||||
* Typically an array is compressed using unishox2_compress_lines() and \n
|
||||
* a header (.h) file is generated using the resultant compressed array. \n
|
||||
* This header file can be used in another program with another decompress \n
|
||||
* routine which takes this compressed array as parameter and index to be \n
|
||||
* decompressed.
|
||||
*/
|
||||
extern int unishox2_decompress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(char *out, int olen),
|
||||
const unsigned char usx_hcodes[], const unsigned char usx_hcode_lens[],
|
||||
const char *usx_freq_seq[], const char *usx_templates[],
|
||||
struct us_lnk_lst *prev_lines);
|
||||
|
||||
#endif
|
||||
@@ -129,7 +129,7 @@ extern const pb_msgdesc_t AdminMessage_msg;
|
||||
#define AdminMessage_fields &AdminMessage_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define AdminMessage_size 610
|
||||
#define AdminMessage_size 598
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -61,6 +61,10 @@ typedef enum _HardwareModel {
|
||||
HardwareModel_DIY_V1 = 39,
|
||||
/* RAK WisBlock ESP32 core: https://docs.rakwireless.com/Product-Categories/WisBlock/RAK11200/Overview/ */
|
||||
HardwareModel_RAK11200 = 40,
|
||||
/* B&Q Consulting Nano Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:nano */
|
||||
HardwareModel_NANO_G1 = 41,
|
||||
/* nRF52840 Dongle : https://www.nordicsemi.com/Products/Development-hardware/nrf52840-dongle/ */
|
||||
HardwareModel_NRF52840_PCA10059 = 42,
|
||||
/* 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. */
|
||||
HardwareModel_PRIVATE_HW = 255
|
||||
} HardwareModel;
|
||||
@@ -496,6 +500,7 @@ typedef struct _User {
|
||||
} User;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(237) Data_payload_t;
|
||||
typedef PB_BYTES_ARRAY_T(237) Data_payload_compressed_t;
|
||||
/* (Formerly called SubPacket)
|
||||
The payload portion fo a packet, this is the actual bytes that are sent
|
||||
inside a radio packet (because from/to are broken out by the comms library) */
|
||||
@@ -503,30 +508,34 @@ typedef struct _Data {
|
||||
/* Formerly named typ and of type Type */
|
||||
PortNum portnum;
|
||||
/* TODO: REPLACE */
|
||||
Data_payload_t payload;
|
||||
pb_size_t which_payloadVariant;
|
||||
union {
|
||||
Data_payload_t payload;
|
||||
Data_payload_compressed_t payload_compressed;
|
||||
};
|
||||
/* TODO: REPLACE */
|
||||
bool want_response;
|
||||
/* Not normally used, but for testing a sender can request that recipient
|
||||
responds in kind (i.e. if it received a position, it should unicast back it's position).
|
||||
Note: that if you set this on a broadcast you will receive many replies. */
|
||||
bool want_response;
|
||||
uint32_t dest;
|
||||
/* The address of the destination node.
|
||||
This field is is filled in by the mesh radio device software, application
|
||||
layer software should never need it.
|
||||
RouteDiscovery messages _must_ populate this.
|
||||
Other message types might need to if they are doing multihop routing. */
|
||||
uint32_t dest;
|
||||
uint32_t source;
|
||||
/* The address of the original sender for this message.
|
||||
This field should _only_ be populated for reliable multihop packets (to keep
|
||||
packets small). */
|
||||
uint32_t source;
|
||||
uint32_t request_id;
|
||||
/* Only used in routing or response messages.
|
||||
Indicates the original message ID that this message is reporting failure on. (formerly called original_id) */
|
||||
uint32_t request_id;
|
||||
/* If set, this message is intened to be a reply to a previously sent message with the defined id. */
|
||||
uint32_t reply_id;
|
||||
/* If set, this message is intened to be a reply to a previously sent message with the defined id. */
|
||||
uint32_t emoji;
|
||||
/* Defaults to false. If true, then what is in the payload should be treated as an emoji like giving
|
||||
a message a heart or poop emoji. */
|
||||
uint32_t emoji;
|
||||
/* Location structure */
|
||||
bool has_location;
|
||||
Location location;
|
||||
} Data;
|
||||
@@ -734,7 +743,7 @@ extern "C" {
|
||||
#define User_init_default {"", "", "", {0}, _HardwareModel_MIN, 0, _Team_MIN, 0, 0, 0}
|
||||
#define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#define Routing_init_default {0, {RouteDiscovery_init_default}}
|
||||
#define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, Location_init_default}
|
||||
#define Data_init_default {_PortNum_MIN, 0, {{0, {0}}}, 0, 0, 0, 0, 0, 0, false, Location_init_default}
|
||||
#define Location_init_default {0, 0, 0, 0, 0}
|
||||
#define MeshPacket_init_default {0, 0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0, _MeshPacket_Delayed_MIN}
|
||||
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0, false, DeviceMetrics_init_default}
|
||||
@@ -747,7 +756,7 @@ extern "C" {
|
||||
#define User_init_zero {"", "", "", {0}, _HardwareModel_MIN, 0, _Team_MIN, 0, 0, 0}
|
||||
#define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#define Routing_init_zero {0, {RouteDiscovery_init_zero}}
|
||||
#define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, Location_init_zero}
|
||||
#define Data_init_zero {_PortNum_MIN, 0, {{0, {0}}}, 0, 0, 0, 0, 0, 0, false, Location_init_zero}
|
||||
#define Location_init_zero {0, 0, 0, 0, 0}
|
||||
#define MeshPacket_init_zero {0, 0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0, _MeshPacket_Delayed_MIN}
|
||||
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0, false, DeviceMetrics_init_zero}
|
||||
@@ -821,6 +830,7 @@ extern "C" {
|
||||
#define User_ant_azimuth_tag 12
|
||||
#define Data_portnum_tag 1
|
||||
#define Data_payload_tag 2
|
||||
#define Data_payload_compressed_tag 10
|
||||
#define Data_want_response_tag 3
|
||||
#define Data_dest_tag 4
|
||||
#define Data_source_tag 5
|
||||
@@ -919,14 +929,15 @@ X(a, STATIC, ONEOF, UENUM, (variant,error_reason,error_reason), 3)
|
||||
|
||||
#define Data_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, portnum, 1) \
|
||||
X(a, STATIC, SINGULAR, BYTES, payload, 2) \
|
||||
X(a, STATIC, ONEOF, BYTES, (payloadVariant,payload,payload), 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, want_response, 3) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, dest, 4) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, source, 5) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, request_id, 6) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, reply_id, 7) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, emoji, 8) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, location, 9)
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, location, 9) \
|
||||
X(a, STATIC, ONEOF, BYTES, (payloadVariant,payload_compressed,payload_compressed), 10)
|
||||
#define Data_CALLBACK NULL
|
||||
#define Data_DEFAULT NULL
|
||||
#define Data_location_MSGTYPE Location
|
||||
|
||||
@@ -260,11 +260,9 @@ typedef enum _RadioConfig_UserPreferences_TelemetrySensorType {
|
||||
/* Struct definitions */
|
||||
typedef struct _RadioConfig_UserPreferences {
|
||||
uint32_t position_broadcast_secs;
|
||||
uint32_t send_owner_interval;
|
||||
uint32_t wait_bluetooth_secs;
|
||||
uint32_t screen_on_secs;
|
||||
uint32_t phone_timeout_secs;
|
||||
uint32_t phone_sds_timeout_sec;
|
||||
uint32_t mesh_sds_timeout_secs;
|
||||
uint32_t sds_secs;
|
||||
uint32_t ls_secs;
|
||||
@@ -401,17 +399,15 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default}
|
||||
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _Role_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_Serial_Mode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_TelemetrySensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, _InputEventChar_MIN, _InputEventChar_MIN, _InputEventChar_MIN, 0, 0, "", 0, 0, 0, _RadioConfig_UserPreferences_Serial_Baud_MIN, 0}
|
||||
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _Role_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_Serial_Mode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_TelemetrySensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, _InputEventChar_MIN, _InputEventChar_MIN, _InputEventChar_MIN, 0, 0, "", 0, 0, 0, _RadioConfig_UserPreferences_Serial_Baud_MIN, 0}
|
||||
#define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero}
|
||||
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _Role_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_Serial_Mode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_TelemetrySensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, _InputEventChar_MIN, _InputEventChar_MIN, _InputEventChar_MIN, 0, 0, "", 0, 0, 0, _RadioConfig_UserPreferences_Serial_Baud_MIN, 0}
|
||||
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _Role_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_Serial_Mode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_TelemetrySensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, _InputEventChar_MIN, _InputEventChar_MIN, _InputEventChar_MIN, 0, 0, "", 0, 0, 0, _RadioConfig_UserPreferences_Serial_Baud_MIN, 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define RadioConfig_UserPreferences_position_broadcast_secs_tag 1
|
||||
#define RadioConfig_UserPreferences_send_owner_interval_tag 2
|
||||
#define RadioConfig_UserPreferences_wait_bluetooth_secs_tag 4
|
||||
#define RadioConfig_UserPreferences_screen_on_secs_tag 5
|
||||
#define RadioConfig_UserPreferences_phone_timeout_secs_tag 6
|
||||
#define RadioConfig_UserPreferences_phone_sds_timeout_sec_tag 7
|
||||
#define RadioConfig_UserPreferences_mesh_sds_timeout_secs_tag 8
|
||||
#define RadioConfig_UserPreferences_sds_secs_tag 9
|
||||
#define RadioConfig_UserPreferences_ls_secs_tag 10
|
||||
@@ -502,11 +498,9 @@ X(a, STATIC, OPTIONAL, MESSAGE, preferences, 1)
|
||||
|
||||
#define RadioConfig_UserPreferences_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_broadcast_secs, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, send_owner_interval, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, wait_bluetooth_secs, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, screen_on_secs, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, phone_timeout_secs, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, phone_sds_timeout_sec, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, mesh_sds_timeout_secs, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, sds_secs, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ls_secs, 10) \
|
||||
@@ -597,8 +591,8 @@ extern const pb_msgdesc_t RadioConfig_UserPreferences_msg;
|
||||
#define RadioConfig_UserPreferences_fields &RadioConfig_UserPreferences_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define RadioConfig_UserPreferences_size 604
|
||||
#define RadioConfig_size 607
|
||||
#define RadioConfig_UserPreferences_size 592
|
||||
#define RadioConfig_size 595
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -40,10 +40,10 @@ typedef struct _EnvironmentMetrics {
|
||||
|
||||
/* Types of Measurements the telemetry module is equipped to handle */
|
||||
typedef struct _Telemetry {
|
||||
/* This is usually not sent over the mesh (to save space), but it is sent
|
||||
from the phone so that the local device can set its RTC If it is sent over
|
||||
the mesh (because there are devices on the mesh without GPS), it will only
|
||||
be sent by devices which has a hardware GPS clock (IE Mobile Phone).
|
||||
/* This is usually not sent over the mesh (to save space), but it is sent
|
||||
from the phone so that the local device can set its RTC If it is sent over
|
||||
the mesh (because there are devices on the mesh without GPS), it will only
|
||||
be sent by devices which has a hardware GPS clock (IE Mobile Phone).
|
||||
seconds since 1970 */
|
||||
uint32_t time;
|
||||
/* Key native device metrics such as battery level */
|
||||
|
||||
@@ -8,10 +8,11 @@
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include "power.h"
|
||||
#include "sleep.h"
|
||||
#include <FSCommon.h>
|
||||
#include <HTTPBodyParser.hpp>
|
||||
#include <HTTPMultipartBodyParser.hpp>
|
||||
#include <HTTPURLEncodedBodyParser.hpp>
|
||||
#include <FSCommon.h>
|
||||
#include <json11.hpp>
|
||||
|
||||
#ifndef NO_ESP32
|
||||
#include "esp_task_wdt.h"
|
||||
@@ -272,8 +273,6 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res)
|
||||
DEBUG_MSG("webAPI handleAPIv1ToRadio\n");
|
||||
}
|
||||
|
||||
bool firstFile = 1;
|
||||
|
||||
void htmlDeleteDir(const char * dirname)
|
||||
{
|
||||
File root = FSCom.open(dirname);
|
||||
@@ -301,70 +300,72 @@ void htmlDeleteDir(const char * dirname)
|
||||
root.close();
|
||||
}
|
||||
|
||||
void htmlListDir(HTTPResponse *res, const char * dirname, uint8_t levels)
|
||||
std::vector<std::map<char *, char *>>* htmlListDir(std::vector<std::map<char *, char *>> *fileList, const char *dirname, uint8_t levels)
|
||||
{
|
||||
File root = FSCom.open(dirname);
|
||||
if(!root){
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
if(!root.isDirectory()){
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// iterate over the file list
|
||||
File file = root.openNextFile();
|
||||
while(file){
|
||||
if(file.isDirectory() && !String(file.name()).endsWith(".")) {
|
||||
if(levels){
|
||||
htmlListDir(res, file.name(), levels -1);
|
||||
htmlListDir(fileList, file.name(), levels -1);
|
||||
}
|
||||
} else {
|
||||
if (firstFile) {
|
||||
firstFile = 0;
|
||||
} else {
|
||||
res->println(",");
|
||||
}
|
||||
res->println("{");
|
||||
} else {
|
||||
std::map<char*, char*> thisFileMap;
|
||||
thisFileMap[strdup("size")] = strdup(String(file.size()).c_str());
|
||||
thisFileMap[strdup("name")] = strdup(String(file.name()).substring(1).c_str());
|
||||
if (String(file.name()).substring(1).endsWith(".gz")) {
|
||||
String modifiedFile = String(file.name()).substring(1);
|
||||
modifiedFile.remove((modifiedFile.length() - 3), 3);
|
||||
res->print("\"nameModified\": \"" + modifiedFile + "\",");
|
||||
res->print("\"name\": \"" + String(file.name()).substring(1) + "\",");
|
||||
} else {
|
||||
res->print("\"name\": \"" + String(file.name()).substring(1) + "\",");
|
||||
thisFileMap[strdup("nameModified")] = strdup(modifiedFile.c_str());
|
||||
}
|
||||
res->print("\"size\": " + String(file.size()));
|
||||
res->print("}");
|
||||
fileList->push_back(thisFileMap);
|
||||
}
|
||||
file.close();
|
||||
file = root.openNextFile();
|
||||
}
|
||||
root.close();
|
||||
return fileList;
|
||||
}
|
||||
|
||||
void handleFsBrowseStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
|
||||
res->setHeader("Content-Type", "application/json");
|
||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||
res->setHeader("Access-Control-Allow-Methods", "GET");
|
||||
res->println("{");
|
||||
res->println("\"data\": {");
|
||||
res->print("\"files\": [");
|
||||
htmlListDir(res, "/", 10);
|
||||
res->print("],");
|
||||
res->print("\"filesystem\" : {");
|
||||
res->print("\"total\" : " + String(FSCom.totalBytes()) + ",");
|
||||
res->print("\"used\" : " + String(FSCom.usedBytes()) + ",");
|
||||
res->print("\"free\" : " + String(FSCom.totalBytes() - FSCom.usedBytes()));
|
||||
res->println("}");
|
||||
res->println("},");
|
||||
res->println("\"status\": \"ok\"");
|
||||
res->println("}");
|
||||
}
|
||||
|
||||
using namespace json11;
|
||||
auto fileList = htmlListDir(new std::vector<std::map<char *, char *>>(), "/", 10);
|
||||
|
||||
// create json output structure
|
||||
Json filesystemObj = Json::object{
|
||||
{"total", String(FSCom.totalBytes()).c_str()},
|
||||
{"used", String(FSCom.usedBytes()).c_str()},
|
||||
{"free", String(FSCom.totalBytes() - FSCom.usedBytes()).c_str()},
|
||||
};
|
||||
|
||||
Json jsonObjInner = Json::object{{"files", Json(*fileList)},
|
||||
{"filesystem", filesystemObj}
|
||||
};
|
||||
|
||||
Json jsonObjOuter = Json::object{{"data", jsonObjInner}, {"status", "ok"}};
|
||||
|
||||
// serialize and write it to the stream
|
||||
std::string jsonStr = jsonObjOuter.dump();
|
||||
res->print(jsonStr.c_str());
|
||||
}
|
||||
|
||||
void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
using namespace json11;
|
||||
|
||||
ResourceParameters *params = req->getParams();
|
||||
std::string paramValDelete;
|
||||
|
||||
@@ -375,15 +376,15 @@ void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res)
|
||||
std::string pathDelete = "/" + paramValDelete;
|
||||
if (FSCom.remove(pathDelete.c_str())) {
|
||||
Serial.println(pathDelete.c_str());
|
||||
res->println("{");
|
||||
res->println("\"status\": \"ok\"");
|
||||
res->println("}");
|
||||
Json jsonObjOuter = Json::object{{"status", "ok"}};
|
||||
std::string jsonStr = jsonObjOuter.dump();
|
||||
res->print(jsonStr.c_str());
|
||||
return;
|
||||
} else {
|
||||
Serial.println(pathDelete.c_str());
|
||||
res->println("{");
|
||||
res->println("\"status\": \"Error\"");
|
||||
res->println("}");
|
||||
Json jsonObjOuter = Json::object{{"status", "Error"}};
|
||||
std::string jsonStr = jsonObjOuter.dump();
|
||||
res->print(jsonStr.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -600,6 +601,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
|
||||
|
||||
void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
using namespace json11;
|
||||
|
||||
ResourceParameters *params = req->getParams();
|
||||
std::string content;
|
||||
@@ -618,104 +620,89 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||
res->println("<pre>");
|
||||
}
|
||||
|
||||
res->println("{");
|
||||
|
||||
res->println("\"data\": {");
|
||||
|
||||
res->println("\"airtime\": {");
|
||||
|
||||
// data->airtime->tx_log
|
||||
std::vector<String> txLogValues;
|
||||
uint32_t *logArray;
|
||||
|
||||
res->print("\"tx_log\": [");
|
||||
|
||||
logArray = airTime->airtimeReport(TX_LOG);
|
||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
||||
uint32_t tmp;
|
||||
tmp = *(logArray + i);
|
||||
res->printf("%d", tmp);
|
||||
if (i != airTime->getPeriodsToLog() - 1) {
|
||||
res->print(", ");
|
||||
}
|
||||
txLogValues.push_back(String(tmp));
|
||||
}
|
||||
|
||||
res->println("],");
|
||||
res->print("\"rx_log\": [");
|
||||
|
||||
// data->airtime->rx_log
|
||||
std::vector<String> rxLogValues;
|
||||
logArray = airTime->airtimeReport(RX_LOG);
|
||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
||||
uint32_t tmp;
|
||||
tmp = *(logArray + i);
|
||||
res->printf("%d", tmp);
|
||||
if (i != airTime->getPeriodsToLog() - 1) {
|
||||
res->print(", ");
|
||||
}
|
||||
rxLogValues.push_back(String(tmp));
|
||||
}
|
||||
|
||||
res->println("],");
|
||||
res->print("\"rx_all_log\": [");
|
||||
|
||||
// data->airtime->rx_all_log
|
||||
std::vector<String> rxAllLogValues;
|
||||
logArray = airTime->airtimeReport(RX_ALL_LOG);
|
||||
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
|
||||
uint32_t tmp;
|
||||
tmp = *(logArray + i);
|
||||
res->printf("%d", tmp);
|
||||
if (i != airTime->getPeriodsToLog() - 1) {
|
||||
res->print(", ");
|
||||
}
|
||||
rxAllLogValues.push_back(String(tmp));
|
||||
}
|
||||
|
||||
res->println("],");
|
||||
res->printf("\"channel_utilization\": %3.2f%,\n", airTime->channelUtilizationPercent());
|
||||
res->printf("\"utilization_tx\": %3.2f%,\n", airTime->utilizationTXPercent());
|
||||
res->printf("\"seconds_since_boot\": %u,\n", airTime->getSecondsSinceBoot());
|
||||
res->printf("\"seconds_per_period\": %u,\n", airTime->getSecondsPerPeriod());
|
||||
res->printf("\"periods_to_log\": %u\n", airTime->getPeriodsToLog());
|
||||
|
||||
res->println("},");
|
||||
|
||||
res->println("\"wifi\": {");
|
||||
|
||||
res->println("\"rssi\": " + String(WiFi.RSSI()) + ",");
|
||||
Json jsonObjAirtime = Json::object{
|
||||
{"tx_log", Json(txLogValues)},
|
||||
{"rx_log", Json(rxLogValues)},
|
||||
{"rx_all_log", Json(rxAllLogValues)},
|
||||
{"channel_utilization", Json(airTime->channelUtilizationPercent())},
|
||||
{"utilization_tx", Json(airTime->utilizationTXPercent())},
|
||||
{"seconds_since_boot", Json(int(airTime->getSecondsSinceBoot()))},
|
||||
{"seconds_per_period", Json(int(airTime->getSecondsPerPeriod()))},
|
||||
{"periods_to_log", Json(airTime->getPeriodsToLog())},
|
||||
};
|
||||
|
||||
// data->wifi
|
||||
String ipStr;
|
||||
if (radioConfig.preferences.wifi_ap_mode || isSoftAPForced()) {
|
||||
res->println("\"ip\": \"" + String(WiFi.softAPIP().toString().c_str()) + "\"");
|
||||
ipStr = String(WiFi.softAPIP().toString());
|
||||
} else {
|
||||
res->println("\"ip\": \"" + String(WiFi.localIP().toString().c_str()) + "\"");
|
||||
ipStr = String(WiFi.localIP().toString());
|
||||
}
|
||||
Json jsonObjWifi = Json::object{
|
||||
{"rssi", String(WiFi.RSSI())},
|
||||
{"ip", ipStr.c_str()}
|
||||
};
|
||||
|
||||
res->println("},");
|
||||
// data->memory
|
||||
Json jsonObjMemory = Json::object{{"heap_total", Json(int(ESP.getHeapSize()))},
|
||||
{"heap_free", Json(int(ESP.getFreeHeap()))},
|
||||
{"psram_total", Json(int(ESP.getPsramSize()))},
|
||||
{"psram_free", Json(int(ESP.getFreePsram()))},
|
||||
{"fs_total", String(FSCom.totalBytes()).c_str()},
|
||||
{"fs_used", String(FSCom.usedBytes()).c_str()},
|
||||
{"fs_free", String(FSCom.totalBytes() - FSCom.usedBytes()).c_str()}};
|
||||
|
||||
res->println("\"memory\": {");
|
||||
res->printf("\"heap_total\": %d,\n", ESP.getHeapSize());
|
||||
res->printf("\"heap_free\": %d,\n", ESP.getFreeHeap());
|
||||
res->printf("\"psram_total\": %d,\n", ESP.getPsramSize());
|
||||
res->printf("\"psram_free\": %d,\n", ESP.getFreePsram());
|
||||
res->println("\"fs_total\" : " + String(FSCom.totalBytes()) + ",");
|
||||
res->println("\"fs_used\" : " + String(FSCom.usedBytes()) + ",");
|
||||
res->println("\"fs_free\" : " + String(FSCom.totalBytes() - FSCom.usedBytes()));
|
||||
res->println("},");
|
||||
// data->power
|
||||
Json jsonObjPower = Json::object{{"battery_percent", Json(powerStatus->getBatteryChargePercent())},
|
||||
{"battery_voltage_mv", Json(powerStatus->getBatteryVoltageMv())},
|
||||
{"has_battery", BoolToString(powerStatus->getHasBattery())},
|
||||
{"has_usb", BoolToString(powerStatus->getHasUSB())},
|
||||
{"is_charging", BoolToString(powerStatus->getIsCharging())}};
|
||||
|
||||
res->println("\"power\": {");
|
||||
res->printf("\"battery_percent\": %u,\n", powerStatus->getBatteryChargePercent());
|
||||
res->printf("\"battery_voltage_mv\": %u,\n", powerStatus->getBatteryVoltageMv());
|
||||
res->printf("\"has_battery\": %s,\n", BoolToString(powerStatus->getHasBattery()));
|
||||
res->printf("\"has_usb\": %s,\n", BoolToString(powerStatus->getHasUSB()));
|
||||
res->printf("\"is_charging\": %s\n", BoolToString(powerStatus->getIsCharging()));
|
||||
res->println("},");
|
||||
// data->device
|
||||
Json jsonObjDevice = Json::object{{"reboot_counter", Json(int(myNodeInfo.reboot_count))}};
|
||||
|
||||
res->println("\"device\": {");
|
||||
res->printf("\"reboot_counter\": %d\n", myNodeInfo.reboot_count);
|
||||
res->println("},");
|
||||
// data->radio
|
||||
Json jsonObjRadio = Json::object{{"frequency", Json(RadioLibInterface::instance->getFreq())},
|
||||
{"lora_channel", Json(int(RadioLibInterface::instance->getChannelNum()))}};
|
||||
|
||||
res->println("\"radio\": {");
|
||||
res->printf("\"frequecy\": %f,\n", RadioLibInterface::instance->getFreq());
|
||||
res->printf("\"lora_channel\": %d\n", RadioLibInterface::instance->getChannelNum());
|
||||
res->println("}");
|
||||
// collect data to inner data object
|
||||
Json jsonObjInner = Json::object{{"airtime", jsonObjAirtime}, {"wifi", jsonObjWifi}, {"memory", jsonObjMemory},
|
||||
{"power", jsonObjPower}, {"device", jsonObjDevice}, {"radio", jsonObjRadio}};
|
||||
|
||||
res->println("},");
|
||||
|
||||
res->println("\"status\": \"ok\"");
|
||||
res->println("}");
|
||||
// create json output structure
|
||||
Json jsonObjOuter = Json::object{{"data", jsonObjInner}, {"status", "ok"}};
|
||||
// serialize and write it to the stream
|
||||
std::string jsonStr = jsonObjOuter.dump();
|
||||
res->print(jsonStr.c_str());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -912,6 +899,8 @@ void handleRestart(HTTPRequest *req, HTTPResponse *res)
|
||||
|
||||
void handleBlinkLED(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
using namespace json11;
|
||||
|
||||
res->setHeader("Content-Type", "application/json");
|
||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||
res->setHeader("Access-Control-Allow-Methods", "POST");
|
||||
@@ -938,28 +927,25 @@ void handleBlinkLED(HTTPRequest *req, HTTPResponse *res)
|
||||
screen->blink();
|
||||
}
|
||||
|
||||
res->println("{");
|
||||
res->println("\"status\": \"ok\"");
|
||||
res->println("}");
|
||||
Json jsonObjOuter = Json::object{{"status", "ok"}};
|
||||
std::string jsonStr = jsonObjOuter.dump();
|
||||
res->print(jsonStr.c_str());
|
||||
}
|
||||
|
||||
void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
using namespace json11;
|
||||
|
||||
res->setHeader("Content-Type", "application/json");
|
||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||
res->setHeader("Access-Control-Allow-Methods", "GET");
|
||||
// res->setHeader("Content-Type", "text/html");
|
||||
|
||||
int n = WiFi.scanNetworks();
|
||||
res->println("{");
|
||||
res->println("\"data\": {");
|
||||
if (n == 0) {
|
||||
// No networks found.
|
||||
res->println("\"networks\": []");
|
||||
|
||||
} else {
|
||||
res->println("\"networks\": [");
|
||||
|
||||
// build list of network objects
|
||||
std::vector<Json> networkObjs;
|
||||
if (n > 0) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
char ssidArray[50];
|
||||
String ssidString = String(WiFi.SSID(i));
|
||||
@@ -967,19 +953,20 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
|
||||
ssidString.toCharArray(ssidArray, 50);
|
||||
|
||||
if (WiFi.encryptionType(i) != WIFI_AUTH_OPEN) {
|
||||
res->printf("{\"ssid\": \"%s\",\"rssi\": %d}", ssidArray, WiFi.RSSI(i));
|
||||
if (i != n - 1) {
|
||||
res->printf(",");
|
||||
}
|
||||
Json thisNetwork = Json::object{{"ssid", ssidArray}, {"rssi", WiFi.RSSI(i)}};
|
||||
networkObjs.push_back(thisNetwork);
|
||||
}
|
||||
// Yield some cpu cycles to IP stack.
|
||||
// This is important in case the list is large and it takes us time to return
|
||||
// to the main loop.
|
||||
yield();
|
||||
}
|
||||
res->println("]");
|
||||
}
|
||||
res->println("},");
|
||||
res->println("\"status\": \"ok\"");
|
||||
res->println("}");
|
||||
|
||||
// build output structure
|
||||
Json jsonObjOuter = Json::object{{"data", networkObjs}, {"status", "ok"}};
|
||||
|
||||
// serialize and write it to the stream
|
||||
std::string jsonStr = jsonObjOuter.dump();
|
||||
res->print(jsonStr.c_str());
|
||||
}
|
||||
|
||||
@@ -10,10 +10,13 @@
|
||||
#include "target_specific.h"
|
||||
#include <DNSServer.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include <NTPClient.h>
|
||||
#include <WiFi.h>
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
#ifndef DISABLE_NTP
|
||||
#include <NTPClient.h>
|
||||
#endif
|
||||
|
||||
using namespace concurrency;
|
||||
|
||||
static void WiFiEvent(WiFiEvent_t event);
|
||||
@@ -23,7 +26,10 @@ DNSServer dnsServer;
|
||||
|
||||
// NTP
|
||||
WiFiUDP ntpUDP;
|
||||
|
||||
#ifndef DISABLE_NTP
|
||||
NTPClient timeClient(ntpUDP, "0.pool.ntp.org");
|
||||
#endif
|
||||
|
||||
uint8_t wifiDisconnectReason = 0;
|
||||
|
||||
@@ -67,13 +73,13 @@ static int32_t reconnectWiFi()
|
||||
DEBUG_MSG("... Reconnecting to WiFi access point\n");
|
||||
WiFi.mode(WIFI_MODE_STA);
|
||||
WiFi.begin(wifiName, wifiPsw);
|
||||
|
||||
|
||||
// Starting timeClient;
|
||||
}
|
||||
}
|
||||
|
||||
//if (*wifiName) {
|
||||
#ifndef DISABLE_NTP
|
||||
// if (*wifiName) {
|
||||
if (WiFi.isConnected()) {
|
||||
DEBUG_MSG("Updating NTP time\n");
|
||||
if (timeClient.update()) {
|
||||
@@ -89,6 +95,7 @@ static int32_t reconnectWiFi()
|
||||
DEBUG_MSG("NTP Update failed\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 30 * 1000; // every 30 seconds
|
||||
}
|
||||
@@ -155,9 +162,11 @@ static void onNetworkConnected()
|
||||
MDNS.addService("https", "tcp", 443);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_NTP
|
||||
DEBUG_MSG("Starting NTP time client\n");
|
||||
timeClient.begin();
|
||||
timeClient.setUpdateInterval(60*60); // Update once an hour
|
||||
timeClient.setUpdateInterval(60 * 60); // Update once an hour
|
||||
#endif
|
||||
|
||||
initWebServer();
|
||||
initApiServer();
|
||||
|
||||
@@ -290,8 +290,8 @@ String MQTT::downstreamPacketToJson(MeshPacket *mp)
|
||||
memset(&scratch, 0, sizeof(scratch));
|
||||
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &Telemetry_msg,
|
||||
&scratch)) {
|
||||
decoded = &scratch;
|
||||
if (decoded->which_variant == Telemetry_environment_metrics_tag) {
|
||||
decoded = &scratch;
|
||||
msgPayload = Json::object{
|
||||
{"temperature", decoded->variant.environment_metrics.temperature},
|
||||
{"relative_humidity", decoded->variant.environment_metrics.relative_humidity},
|
||||
|
||||
9
variants/Dongle_nRF52840-pca10059-v1/platformio.ini
Normal file
9
variants/Dongle_nRF52840-pca10059-v1/platformio.ini
Normal file
@@ -0,0 +1,9 @@
|
||||
[env:pca10059_diy_eink]
|
||||
extends = nrf52840_base
|
||||
board = nordic_pca10059
|
||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/Dongle_nRF52840-pca10059-v1 -D NORDIC_PCA10059
|
||||
src_filter = ${nrf52_base.src_filter} +<../variants/Dongle_nRF52840-pca10059-v1>
|
||||
lib_deps =
|
||||
${nrf52840_base.lib_deps}
|
||||
https://github.com/ZinggJM/GxEPD2.git
|
||||
debug_tool = jlink
|
||||
43
variants/Dongle_nRF52840-pca10059-v1/variant.cpp
Normal file
43
variants/Dongle_nRF52840-pca10059-v1/variant.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
|
||||
Copyright (c) 2016 Sandeep Mistry All right reserved.
|
||||
Copyright (c) 2018, Adafruit Industries (adafruit.com)
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "variant.h"
|
||||
#include "wiring_constants.h"
|
||||
#include "wiring_digital.h"
|
||||
#include "nrf.h"
|
||||
|
||||
const uint32_t g_ADigitalPinMap[] =
|
||||
{
|
||||
// P0
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31,
|
||||
|
||||
// P1
|
||||
32, 33, 34, 35, 36, 37, 38, 39,
|
||||
40, 41, 42, 43, 44, 45, 46, 47};
|
||||
|
||||
void initVariant()
|
||||
{
|
||||
// LED1 & LED2
|
||||
pinMode(PIN_LED1, OUTPUT);
|
||||
ledOff(PIN_LED1);
|
||||
|
||||
pinMode(PIN_LED2, OUTPUT);
|
||||
ledOff(PIN_LED2);
|
||||
}
|
||||
180
variants/Dongle_nRF52840-pca10059-v1/variant.h
Normal file
180
variants/Dongle_nRF52840-pca10059-v1/variant.h
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
|
||||
Copyright (c) 2016 Sandeep Mistry All right reserved.
|
||||
Copyright (c) 2018, Adafruit Industries (adafruit.com)
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _VARIANT_NORDIC_PCA10059_
|
||||
#define _VARIANT_NORDIC_PCA10059_
|
||||
|
||||
#define PCA10059
|
||||
|
||||
/** Master clock frequency */
|
||||
#define VARIANT_MCK (64000000ul)
|
||||
|
||||
#define USE_LFXO // Board uses 32khz crystal for LF
|
||||
// define USE_LFRC // Board uses RC for LF
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "WVariant.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// Number of pins defined in PinDescription array
|
||||
#define PINS_COUNT (48)
|
||||
#define NUM_DIGITAL_PINS (48)
|
||||
#define NUM_ANALOG_INPUTS (6)
|
||||
#define NUM_ANALOG_OUTPUTS (0)
|
||||
|
||||
// LEDs
|
||||
#define PIN_LED1 (0 + 12) // Blue LED P1.12
|
||||
#define PIN_LED2 (0 + 6) // Built in Green P0.06
|
||||
|
||||
//Green Built in LED1
|
||||
//#define PIN_LED1 (0 + 6) // LED1 P1.15
|
||||
|
||||
//RGB NeoPixel LED2
|
||||
//#define PIN_LED1 (0 + 8) Red
|
||||
//#define PIN_LED1 (32 + 9) Green
|
||||
//#define PIN_LED1 (0 + 12) Blue
|
||||
|
||||
#define LED_BUILTIN PIN_LED1
|
||||
#define LED_CONN PIN_LED2
|
||||
|
||||
#define LED_GREEN PIN_LED1
|
||||
#define LED_BLUE PIN_LED2
|
||||
|
||||
#define LED_STATE_ON 0 // State when LED is litted
|
||||
|
||||
/*
|
||||
* Buttons
|
||||
*/
|
||||
|
||||
#define PIN_BUTTON1 (32 + 6) // BTN_DN P1.06 Built in button
|
||||
|
||||
/*
|
||||
* Analog pins
|
||||
*/
|
||||
#define PIN_A0 (-1)
|
||||
|
||||
static const uint8_t A0 = PIN_A0;
|
||||
#define ADC_RESOLUTION 14
|
||||
|
||||
// Other pins
|
||||
#define PIN_AREF (-1) // AREF Not yet used
|
||||
|
||||
|
||||
static const uint8_t AREF = PIN_AREF;
|
||||
|
||||
/*
|
||||
* Serial interfaces
|
||||
*/
|
||||
#define PIN_SERIAL1_RX (-1)
|
||||
#define PIN_SERIAL1_TX (-1)
|
||||
|
||||
// Connected to Jlink CDC
|
||||
#define PIN_SERIAL2_RX (-1)
|
||||
#define PIN_SERIAL2_TX (-1)
|
||||
|
||||
/*
|
||||
* SPI Interfaces
|
||||
*/
|
||||
#define SPI_INTERFACES_COUNT 2
|
||||
|
||||
#define PIN_SPI_MISO (0 + 17) // MISO P0.17
|
||||
#define PIN_SPI_MOSI (0 + 15) // MOSI P0.15
|
||||
#define PIN_SPI_SCK (0 + 13) // SCK P0.13
|
||||
|
||||
#define PIN_SPI1_MISO (-1) //
|
||||
#define PIN_SPI1_MOSI (10) // EPD_MOSI P0.10
|
||||
#define PIN_SPI1_SCK (9) // EPD_SCLK P0.09
|
||||
|
||||
static const uint8_t SS = (0 + 31); // LORA_CS P0.31
|
||||
static const uint8_t MOSI = PIN_SPI_MOSI;
|
||||
static const uint8_t MISO = PIN_SPI_MISO;
|
||||
static const uint8_t SCK = PIN_SPI_SCK;
|
||||
|
||||
/*
|
||||
* eink display pins
|
||||
*/
|
||||
|
||||
//#define PIN_EINK_EN (-1)
|
||||
#define PIN_EINK_EN (0 + 6) // Turn on the Green built in LED
|
||||
#define PIN_EINK_CS (32) // EPD_CS
|
||||
#define PIN_EINK_BUSY (20) // EPD_BUSY
|
||||
#define PIN_EINK_DC (24) // EPD_D/C
|
||||
#define PIN_EINK_RES (-1) // Not Connected P0.22 available
|
||||
#define PIN_EINK_SCLK (9) // EPD_SCLK
|
||||
#define PIN_EINK_MOSI (10) // EPD_MOSI
|
||||
|
||||
#define HAS_EINK
|
||||
|
||||
/*
|
||||
* Wire Interfaces
|
||||
*/
|
||||
#define WIRE_INTERFACES_COUNT 1
|
||||
|
||||
#define PIN_WIRE_SDA (32 + 4) // SDA
|
||||
#define PIN_WIRE_SCL (32 + 7) // SCL
|
||||
|
||||
// NiceRF 868 LoRa module
|
||||
#define USE_SX1262
|
||||
#define SX126X_CS (0 + 31) // LORA_CS P0.31
|
||||
#define SX126X_DIO1 (0 + 29) // DIO1 P0.29
|
||||
#define SX126X_BUSY (0 + 2) // LORA_BUSY P0.02
|
||||
#define SX126X_RESET (32 + 15) // LORA_RESET P1.15
|
||||
#define SX126X_TXEN (-1) // TXEN P1.13 NiceRF 868 dont use
|
||||
#define SX126X_RXEN (-1) // RXEN P1.10 NiceRF 868 dont use
|
||||
#define SX126X_E22
|
||||
|
||||
#define PIN_GPS_EN (-1)
|
||||
#define PIN_GPS_PPS (-1) // Pulse per second input from the GPS
|
||||
|
||||
#define GPS_RX_PIN PIN_SERIAL1_RX
|
||||
#define GPS_TX_PIN PIN_SERIAL1_TX
|
||||
|
||||
// Battery
|
||||
// The battery sense is hooked to pin A0 (5)
|
||||
#define BATTERY_PIN PIN_A0
|
||||
// and has 12 bit resolution
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS 12
|
||||
#define BATTERY_SENSE_RESOLUTION 4096.0
|
||||
// Definition of milliVolt per LSB => 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096
|
||||
#define VBAT_MV_PER_LSB (0.73242188F)
|
||||
// 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)
|
||||
// Fixed calculation of milliVolt from compensation value
|
||||
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
|
||||
#undef AREF_VOLTAGE
|
||||
#define AREF_VOLTAGE 3.0
|
||||
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
|
||||
#define ADC_MULTIPLIER VBAT_DIVIDER_COMP //REAL_VBAT_MV_PER_LSB
|
||||
#define VBAT_RAW_TO_SCALED(x) (REAL_VBAT_MV_PER_LSB * x)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Arduino objects - C++ only
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
8
variants/nano-g1/platformio.ini
Normal file
8
variants/nano-g1/platformio.ini
Normal file
@@ -0,0 +1,8 @@
|
||||
; The 1.0 release of the nano-g1 board
|
||||
[env:nano-g1]
|
||||
extends = esp32_base
|
||||
board = ttgo-t-beam
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D NANO_G1 -I variants/nano-g1
|
||||
30
variants/nano-g1/variant.h
Normal file
30
variants/nano-g1/variant.h
Normal file
@@ -0,0 +1,30 @@
|
||||
// #define BUTTON_NEED_PULLUP // if set we need to turn on the internal CPU pullup during sleep
|
||||
|
||||
#define I2C_SDA 21
|
||||
#define I2C_SCL 22
|
||||
|
||||
#define BUTTON_PIN 36 // The middle button GPIO on the Nano G1
|
||||
//#define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed. Does anyone use this? It is not documented anywhere.
|
||||
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Module.
|
||||
|
||||
// common pinout for their SX1262 vs RF95 modules - both can be enabled and we will probe at runtime for RF95 and if
|
||||
// not found then probe for SX1262
|
||||
#define USE_RF95
|
||||
#define USE_SX1262
|
||||
|
||||
#define LORA_DIO0 26 // a No connect on the SX1262 module
|
||||
#define LORA_RESET 23
|
||||
#define LORA_DIO1 33 // SX1262 IRQ
|
||||
#define LORA_DIO2 32 // SX1262 BUSY
|
||||
#define LORA_DIO3 // Not connected on PCB
|
||||
|
||||
#ifdef USE_SX1262
|
||||
#define SX126X_CS RF95_NSS // FIXME - we really should define LORA_CS instead
|
||||
#define SX126X_DIO1 LORA_DIO1
|
||||
#define SX126X_BUSY LORA_DIO2
|
||||
#define SX126X_RESET LORA_RESET
|
||||
#define SX126X_E22 // Not really an E22
|
||||
// Internally the module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
|
||||
// code)
|
||||
#endif
|
||||
|
||||
@@ -22,7 +22,5 @@
|
||||
|
||||
#define USE_RF95
|
||||
#define LORA_DIO0 26 // a No connect on the SX1262 module
|
||||
#define LORA_RESET 14
|
||||
#define LORA_DIO1 35 // Not really used
|
||||
#define LORA_DIO2 34 // Not really used
|
||||
#define LORA_RESET 23
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[VERSION]
|
||||
major = 1
|
||||
minor = 3
|
||||
build = 5
|
||||
build = 7
|
||||
|
||||
Reference in New Issue
Block a user