Compare commits

..

39 Commits

Author SHA1 Message Date
Jm Casler
90df7c2488 bump to 1.3.8 2022-04-18 17:20:03 -07:00
Jm Casler
8c1a81c03a Merge branch 'compression' into master 2022-04-18 17:02:45 -07:00
Jm Casler
6fe9f0b42f Disable compression / decompression (for testing) 2022-04-18 17:00:36 -07:00
Thomas Göttgens
43f6f61472 Merge pull request #1387 from meshtastic/patch-1
tryfix #1363
2022-04-18 23:01:07 +02:00
Thomas Göttgens
ed62b6916c tryfix #1363
Ask for the register several times and only go on if the answer is the same in 2 consecutive tries.
2022-04-18 22:46:45 +02:00
Thomas Göttgens
cf45e4fce5 Merge pull request #1386 from meshtastic/patch-1
Remove References to Pre-1.2 Preffile
2022-04-18 22:19:58 +02:00
Thomas Göttgens
136e2e96f7 Remove References to Pre-1.2 Preffile
1.3+ need a clean install anyway, so no point migrating these any more.
2022-04-18 21:55:58 +02:00
Jm Casler
7c071e2361 updating proto submodule to latest 2022-04-18 12:29:20 -07:00
Thomas Göttgens
0b85e97087 Merge pull request #1385 from meshtastic/oem-screen
Enable OEM Bootlogo, needs protobuf update
2022-04-18 18:43:47 +02:00
Thomas Göttgens
81d1cc1003 Merge branch 'oem-screen' of github.com:meshtastic/Meshtastic-device into oem-screen 2022-04-18 18:27:37 +02:00
Thomas Göttgens
748416d9e3 protobuf update 2022-04-18 18:27:17 +02:00
Thomas Göttgens
da6d49385c Merge branch 'master' into oem-screen 2022-04-18 18:18:19 +02:00
Thomas Göttgens
f279f9614e Enable OEM Bootlogo, needs protobuf update 2022-04-18 18:11:17 +02:00
Sacha Weatherstone
9097475149 Add Repobeats stats image to readme 2022-04-18 23:56:16 +10:00
Jm Casler
5327d6162a remove targz library 2022-04-15 23:17:30 -07:00
Jm Casler
5d7990667d Max nodes to 64 and remove targz 2022-04-15 23:16:40 -07:00
Jm Casler
79a41bd81c updating proto submodule to latest 2022-04-15 22:30:21 -07:00
Jm Casler
6a3d81eff8 Merge pull request #1383 from mc-hamster/compression
Change to unishox library
2022-04-15 20:46:04 -07:00
Jm Casler
7cd66b2b68 Merge branch 'meshtastic:master' into compression 2022-04-15 20:45:44 -07:00
Jm Casler
8124ecbfd8 Change to unishox library 2022-04-15 18:11:17 -07:00
Jm Casler
7df1a64b52 Merge pull request #1382 from mc-hamster/compression
Updated welcome screen w/ text, pages and logo
2022-04-14 21:33:19 -07:00
Jm Casler
e51b7c3c32 Merge branch 'meshtastic:master' into compression 2022-04-14 21:32:52 -07:00
Jm Casler
0c285aac6e enable welcome text 2022-04-14 21:32:00 -07:00
Jm Casler
fbeb554186 Merge branch 'compression' of https://github.com/mc-hamster/Meshtastic-device into compression 2022-04-14 21:31:38 -07:00
Jm Casler
87da779478 Updated welcome screen w/ text, pages and logo
Updated welcome screen w/ text, pages and logo
2022-04-14 21:31:31 -07:00
Jm Casler
1082c5d771 Merge pull request #1381 from mc-hamster/compression
Fix for welcome screen going over ble pairing
2022-04-14 21:05:21 -07:00
Jm Casler
3933d24d62 Merge branch 'meshtastic:master' into compression 2022-04-14 21:03:18 -07:00
Jm Casler
fc0508f254 Fix for welcome screen going over ble pairing 2022-04-14 21:02:52 -07:00
Jm Casler
bb22b6ec58 bump to 1.3.7 2022-04-14 16:15:19 -07:00
Jm Casler
ddb9678377 Merge pull request #1380 from mc-hamster/compression
Compression WIP
2022-04-14 16:14:31 -07:00
Jm Casler
dc20cbb672 one more fix for cppcheck 2022-04-14 15:57:31 -07:00
Jm Casler
a10ea604af Fixes for cppcheck errors 2022-04-14 15:51:48 -07:00
Jm Casler
fb1caa51d0 Merge branch 'meshtastic:master' into compression 2022-04-13 21:59:42 -07:00
Jm Casler
7e977aea00 Add welcome screen feature toggle 2022-04-13 21:59:25 -07:00
Jm Casler
ecc114f1cd temp work on compression 2022-04-13 19:23:35 -07:00
Balázs Kelemen
b76424db50 Make Observer to be able to observe multiple Observables. (#1234)
* Make Observer to be able to observe multiple Observables.

* Fix Observer destructor cleanup.

Co-authored-by: Sacha Weatherstone <sachaw100@hotmail.com>
2022-04-14 08:43:06 +10:00
Jm Casler
b056081d3c Merge branch 'meshtastic:master' into compression 2022-04-12 21:14:25 -07:00
Jm Casler
a4bdef4151 compression WIP
compression works. next is to store it in the proto as a oneof and then decompress it on use.
2022-04-11 22:12:04 -07:00
Jm Casler
478274aff1 Beginning of compression 2022-04-11 20:09:48 -07:00
20 changed files with 1952 additions and 233 deletions

View File

@@ -17,3 +17,7 @@ Manual Method
[For nRF52 devices click here](https://meshtastic.org/docs/getting-started/flashing-nrf52)
For developer information and specific building instructions, please see the [developer documentation](https://meshtastic.org/docs/developers)
## Stats
![Alt](https://repobeats.axiom.co/api/embed/99a2cf5622bb4807f9e8c3b86589f1133cce58a2.svg 'Repobeats analytics image')

View File

@@ -102,7 +102,6 @@ lib_deps =
${environmental.lib_deps}
https://github.com/meshtastic/esp32_https_server.git
h2zero/NimBLE-Arduino@1.3.7
tobozo/ESP32-targz@^1.1.4
arduino-libraries/NTPClient@^3.1.0
lorol/LittleFS_esp32@^1.0.6
lib_ignore =
@@ -110,11 +109,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

2
proto

Submodule proto updated: 870a62b27e...8bac81b631

View File

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

View File

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

View File

@@ -6,21 +6,28 @@
uint8_t oled_probe(byte addr)
{
uint8_t r = 0;
uint8_t r_prev = 0;
uint8_t c = 0;
uint8_t o_probe = 0;
Wire.beginTransmission(addr);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom((int)addr, 1);
if (Wire.available()) {
r = Wire.read();
}
r &= 0x0f;
if (r == 0x08 || r == 0x00) {
o_probe = 2; // SH1106
} else if ( r == 0x03 || r == 0x06 || r == 0x07) {
o_probe = 1; // SSD1306
}
DEBUG_MSG("0x%x subtype probed\n", r);
do {
r_prev = r;
Wire.beginTransmission(addr);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom((int)addr, 1);
if (Wire.available()) {
r = Wire.read();
}
r &= 0x0f;
if (r == 0x08 || r == 0x00) {
o_probe = 2; // SH1106
} else if ( r == 0x03 || r == 0x06 || r == 0x07) {
o_probe = 1; // SSD1306
}
c++;
} while ((r != r_prev) && (c < 4));
DEBUG_MSG("0x%x subtype probed in %i tries \n", r, c);
return o_probe;
}

View File

@@ -95,8 +95,8 @@ bool GPS::setup()
GPS::~GPS()
{
// we really should unregister our sleep observer
notifySleepObserver.unobserve();
notifyDeepSleepObserver.unobserve();
notifySleepObserver.unobserve(&notifySleep);
notifyDeepSleepObserver.unobserve(&notifyDeepSleep);
}
bool GPS::hasLock() { return hasValidLocation; }

View File

@@ -31,6 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "graphics/images.h"
#include "main.h"
#include "mesh-pb-constants.h"
#include "mesh/generated/deviceonly.pb.h"
#include "mesh/Channels.h"
#include "modules/TextMessageModule.h"
#include "sleep.h"
@@ -44,6 +45,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
using namespace meshtastic; /** @todo remove */
extern bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct);
namespace graphics
{
@@ -77,6 +80,10 @@ static char ourId[5];
// GeoCoord object for the screen
GeoCoord geoCoord;
// OEM Config File
static const char *oemConfigFile = "/prefs/oem.proto";
OEMStore oemStore;
#ifdef SHOW_REDRAWS
static bool heartbeat = false;
#endif
@@ -148,6 +155,54 @@ static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int1
drawIconScreen(region, display, state, x, y);
}
static void drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
// draw an xbm image.
// Please note that everything that should be transitioned
// needs to be drawn relative to x and y
// draw centered icon left to right and centered above the one line of app text
display->drawXbm(x + (SCREEN_WIDTH - oemStore.oem_icon_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - oemStore.oem_icon_height) / 2 + 2,
oemStore.oem_icon_width, oemStore.oem_icon_height, (const uint8_t *)oemStore.oem_icon_bits.bytes);
switch(oemStore.oem_font){
case 0:
display->setFont(FONT_SMALL);
break;
case 2:
display->setFont(FONT_LARGE);
break;
default:
display->setFont(FONT_MEDIUM);
break;
}
display->setTextAlignment(TEXT_ALIGN_LEFT);
const char *title = oemStore.oem_text;
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
display->setFont(FONT_SMALL);
// Draw region in upper left
if (upperMsg)
display->drawString(x + 0, y + 0, upperMsg);
// Draw version in upper right
char buf[16];
snprintf(buf, sizeof(buf), "%s",
xstr(APP_VERSION_SHORT)); // Note: we don't bother printing region or now, it makes the string too long
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(buf), y + 0, buf);
screen->forceDisplay();
// FIXME - draw serial # somewhere?
}
static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
// Draw region in upper left
const char *region = myRegion ? myRegion->name : NULL;
drawOEMIconScreen(region, display, state, x, y);
}
// Used on boot when a certificate is being created
static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
@@ -172,22 +227,34 @@ static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16
static void drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
display->setFont(FONT_SMALL);
if ((millis() / 10000) % 2) {
display->setFont(FONT_SMALL);
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->drawString(64 + x, y, "Meshtastic :)");
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->drawString(64 + x, y, "//\\ E S H T /\\ S T / C");
display->setTextAlignment(TEXT_ALIGN_LEFT);
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.");
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.");
} else {
display->setFont(FONT_SMALL);
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->drawString(64 + x, y, "//\\ E S H T /\\ S T / C");
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->drawString(x, y + FONT_HEIGHT_SMALL * 2 - 3, "Visit meshtastic.org");
display->drawString(x, y + FONT_HEIGHT_SMALL * 3 - 3, "for more information.");
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "");
}
#ifndef NO_ESP32
yield();
esp_task_wdt_reset();
#endif
}
#ifdef HAS_EINK
@@ -801,8 +868,8 @@ void Screen::setup()
dispdev.setDetected(screen_model);
#endif
// I think this is not needed - redundant with ui.init
// dispdev.resetOrientation();
// Load OEM config from Proto file if existent
loadProto(oemConfigFile, OEMStore_size, sizeof(oemConfigFile), OEMStore_fields, &oemStore);
// Initialising the UI will init the display too.
ui.init();
@@ -855,6 +922,7 @@ void Screen::setup()
// twice initially.
ui.update();
ui.update();
serialSinceMsec = millis();
// Subscribe to status updates
powerStatusObserver.observe(&powerStatus->onNewStatus);
@@ -885,7 +953,7 @@ int32_t Screen::runOnce()
return RUN_SAME;
}
// Show boot screen for first 3 seconds, then switch to normal operation.
// Show boot screen for first 5 seconds, then switch to normal operation.
// serialSinceMsec adjusts for additional serial wait time during nRF52 bootup
static bool showingBootScreen = true;
if (showingBootScreen && (millis() > (5000 + serialSinceMsec))) {
@@ -894,9 +962,26 @@ int32_t Screen::runOnce()
showingBootScreen = false;
}
if (radioConfig.preferences.region == RegionCode_Unset) {
// If we have an OEM Boot screen, toggle after 2,5 seconds
if(strlen(oemStore.oem_text) > 0){
static bool showingOEMBootScreen = true;
if (showingOEMBootScreen && (millis() > (2500 + serialSinceMsec))) {
DEBUG_MSG("Switch to OEM screen...\n");
// Change frames.
static FrameCallback bootOEMFrames[] = {drawOEMBootScreen};
static const int bootOEMFrameCount = sizeof(bootOEMFrames) / sizeof(bootOEMFrames[0]);
ui.setFrames(bootOEMFrames, bootOEMFrameCount);
ui.update();
ui.update();
showingOEMBootScreen = false;
}
}
#ifndef DISABLE_WELCOME_UNSET
if (showingNormalScreen && radioConfig.preferences.region == RegionCode_Unset) {
setWelcomeFrames();
}
#endif
// Process incoming commands.
for (;;) {

View File

@@ -276,11 +276,9 @@ void NodeDB::pickNewNodeNum()
myNodeInfo.my_node_num = r;
}
static const char *preffileOld = "/db.proto";
static const char *preffile = "/prefs/db.proto";
static const char *radiofile = "/prefs/radio.proto";
static const char *channelfile = "/prefs/channels.proto";
// const char *preftmp = "/db.proto.tmp";
/** Load a protobuf from a file, return true for success */
bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct)
@@ -290,13 +288,6 @@ bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_
auto f = FSCom.open(filename);
// FIXME, temporary hack until every node in the universe is 1.2 or later - look for prefs in the old location (so we can
// preserve region)
if (!f && filename == preffile) {
filename = preffileOld;
f = FSCom.open(filename);
}
bool okay = false;
if (f) {
DEBUG_MSG("Loading %s\n", filename);
@@ -399,8 +390,6 @@ void NodeDB::saveToDisk()
saveProto(radiofile, RadioConfig_size, sizeof(RadioConfig), RadioConfig_fields, &radioConfig);
saveChannelsToDisk();
// remove any pre 1.2 pref files, turn on after 1.2 is in beta
// if(okay) FSCom.remove(preffileOld);
} else {
DEBUG_MSG("***** DEVELOPMENT MODE - DO NOT RELEASE - not saving to flash *****\n");
}

View File

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

View File

@@ -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,56 @@ 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;
// 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 (0) {
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;

File diff suppressed because it is too large Load Diff

View 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

View File

@@ -12,4 +12,8 @@ PB_BIND(DeviceState, DeviceState, 4)
PB_BIND(ChannelFile, ChannelFile, 2)
PB_BIND(OEMStore, OEMStore, 2)

View File

@@ -11,6 +11,17 @@
#error Regenerate this file with the current version of nanopb generator.
#endif
/* Enum definitions */
/* TODO: REPLACE */
typedef enum _ScreenFonts {
/* TODO: REPLACE */
ScreenFonts_FONT_SMALL = 0,
/* TODO: REPLACE */
ScreenFonts_FONT_MEDIUM = 1,
/* TODO: REPLACE */
ScreenFonts_FONT_LARGE = 2
} ScreenFonts;
/* Struct definitions */
/* The on-disk saved channels */
typedef struct _ChannelFile {
@@ -33,7 +44,7 @@ typedef struct _DeviceState {
User owner;
/* TODO: REPLACE */
pb_size_t node_db_count;
NodeInfo node_db[80];
NodeInfo node_db[64];
/* Received packets saved for delivery to the phone */
pb_size_t receive_queue_count;
MeshPacket receive_queue[1];
@@ -53,16 +64,38 @@ typedef struct _DeviceState {
bool did_gps_reset;
} DeviceState;
typedef PB_BYTES_ARRAY_T(2048) OEMStore_oem_icon_bits_t;
/* This can be used for customizing the firmware distribution. If populated,
show a secondary bootup screen with cuatom logo and text for 2.5 seconds. */
typedef struct _OEMStore {
/* The Logo width in Px */
uint32_t oem_icon_width;
/* The Logo height in Px */
uint32_t oem_icon_height;
/* The Logo in xbm bytechar format */
OEMStore_oem_icon_bits_t oem_icon_bits;
/* Use this font for the OEM text. */
ScreenFonts oem_font;
/* Use this font for the OEM text. */
char oem_text[40];
} OEMStore;
/* Helper constants for enums */
#define _ScreenFonts_MIN ScreenFonts_FONT_SMALL
#define _ScreenFonts_MAX ScreenFonts_FONT_LARGE
#define _ScreenFonts_ARRAYSIZE ((ScreenFonts)(ScreenFonts_FONT_LARGE+1))
#ifdef __cplusplus
extern "C" {
#endif
/* Initializer values for message structs */
#define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0}
#define ChannelFile_init_default {0, {Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default}}
#define DeviceState_init_zero {false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0}
#define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0}
#define DeviceState_init_zero {false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0}
#define ChannelFile_init_zero {0, {Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero}}
#define OEMStore_init_zero {0, 0, {0, {0}}, _ScreenFonts_MIN, ""}
/* Field tags (for use in manual encoding/decoding) */
#define ChannelFile_channels_tag 1
@@ -74,6 +107,11 @@ extern "C" {
#define DeviceState_version_tag 8
#define DeviceState_no_save_tag 9
#define DeviceState_did_gps_reset_tag 11
#define OEMStore_oem_icon_width_tag 1
#define OEMStore_oem_icon_height_tag 2
#define OEMStore_oem_icon_bits_tag 3
#define OEMStore_oem_font_tag 4
#define OEMStore_oem_text_tag 5
/* Struct field encoding specification for nanopb */
#define DeviceState_FIELDLIST(X, a) \
@@ -99,16 +137,28 @@ X(a, STATIC, REPEATED, MESSAGE, channels, 1)
#define ChannelFile_DEFAULT NULL
#define ChannelFile_channels_MSGTYPE Channel
#define OEMStore_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, oem_icon_width, 1) \
X(a, STATIC, SINGULAR, UINT32, oem_icon_height, 2) \
X(a, STATIC, SINGULAR, BYTES, oem_icon_bits, 3) \
X(a, STATIC, SINGULAR, UENUM, oem_font, 4) \
X(a, STATIC, SINGULAR, STRING, oem_text, 5)
#define OEMStore_CALLBACK NULL
#define OEMStore_DEFAULT NULL
extern const pb_msgdesc_t DeviceState_msg;
extern const pb_msgdesc_t ChannelFile_msg;
extern const pb_msgdesc_t OEMStore_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
#define DeviceState_fields &DeviceState_msg
#define ChannelFile_fields &ChannelFile_msg
#define OEMStore_fields &OEMStore_msg
/* Maximum encoded size of messages (where known) */
#define ChannelFile_size 832
#define DeviceState_size 23903
#define DeviceState_size 19327
#define OEMStore_size 2106
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -500,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) */
@@ -507,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;
@@ -738,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}
@@ -751,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}
@@ -825,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
@@ -923,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

View File

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

View File

@@ -47,11 +47,9 @@ using namespace httpsserver;
#include <WiFiClientSecure.h>
HTTPClient httpClient;
// needed for ESP32-targz
#define DEST_FS_USES_LITTLEFS
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
#define ESP_ARDUINO_VERSION ESP_ARDUINO_VERSION_VAL(1, 0, 4)
#include <ESP32-targz.h>
// We need to specify some content-type mapping, so the resources get delivered with the
// right content type and are displayed correctly in the browser
@@ -63,57 +61,13 @@ char contentTypes[][2][32] = {{".txt", "text/plain"}, {".html", "text/html"}
{".svg", "image/svg+xml"}, {"", ""}};
// const char *tarURL = "https://www.casler.org/temp/meshtastic-web.tar";
const char *tarURL = "https://api-production-871d.up.railway.app/mirror/webui";
const char *certificate = NULL; // change this as needed, leave as is for no TLS check (yolo security)
// const char *tarURL = "https://api-production-871d.up.railway.app/mirror/webui";
// const char *certificate = NULL; // change this as needed, leave as is for no TLS check (yolo security)
// Our API to handle messages to and from the radio.
HttpAPI webAPI;
WiFiClient *getTarHTTPClientPtr(WiFiClientSecure *client, const char *url, const char *cert = NULL)
{
if (cert == NULL) {
// New versions don't have setInsecure
// client->setInsecure();
} else {
client->setCACert(cert);
}
const char *UserAgent = "ESP32-HTTP-GzUpdater-Client";
httpClient.setReuse(true); // handle 301 redirects gracefully
httpClient.setUserAgent(UserAgent);
httpClient.setConnectTimeout(10000); // 10s timeout = 10000
if (!httpClient.begin(*client, url)) {
log_e("Can't open url %s", url);
return nullptr;
}
const char *headerKeys[] = {"location", "redirect", "Content-Type", "Content-Length", "Content-Disposition"};
const size_t numberOfHeaders = 5;
httpClient.collectHeaders(headerKeys, numberOfHeaders);
int httpCode = httpClient.GET();
// file found at server
if (httpCode == HTTP_CODE_FOUND || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String newlocation = "";
String headerLocation = httpClient.header("location");
String headerRedirect = httpClient.header("redirect");
if (headerLocation != "") {
newlocation = headerLocation;
Serial.printf("302 (location): %s => %s\n", url, headerLocation.c_str());
} else if (headerRedirect != "") {
Serial.printf("301 (redirect): %s => %s\n", url, headerLocation.c_str());
newlocation = headerRedirect;
}
httpClient.end();
if (newlocation != "") {
log_w("Found 302/301 location header: %s", newlocation.c_str());
return getTarHTTPClientPtr(client, newlocation.c_str(), cert);
} else {
log_e("Empty redirect !!");
return nullptr;
}
}
if (httpCode != 200)
return nullptr;
return httpClient.getStreamPtr();
}
void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
{
@@ -131,9 +85,9 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
ResourceNode *nodeAdmin = new ResourceNode("/admin", "GET", &handleAdmin);
ResourceNode *nodeAdminSettings = new ResourceNode("/admin/settings", "GET", &handleAdminSettings);
ResourceNode *nodeAdminSettingsApply = new ResourceNode("/admin/settings/apply", "POST", &handleAdminSettingsApply);
ResourceNode *nodeAdminFs = new ResourceNode("/admin/fs", "GET", &handleFs);
ResourceNode *nodeUpdateFs = new ResourceNode("/admin/fs/update", "POST", &handleUpdateFs);
ResourceNode *nodeDeleteFs = new ResourceNode("/admin/fs/delete", "GET", &handleDeleteFsContent);
// ResourceNode *nodeAdminFs = new ResourceNode("/admin/fs", "GET", &handleFs);
// ResourceNode *nodeUpdateFs = new ResourceNode("/admin/fs/update", "POST", &handleUpdateFs);
// ResourceNode *nodeDeleteFs = new ResourceNode("/admin/fs/delete", "GET", &handleDeleteFsContent);
ResourceNode *nodeRestart = new ResourceNode("/restart", "POST", &handleRestart);
ResourceNode *nodeFormUpload = new ResourceNode("/upload", "POST", &handleFormUpload);
@@ -160,10 +114,10 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
secureServer->registerNode(nodeJsonFsBrowseStatic);
secureServer->registerNode(nodeJsonDelete);
secureServer->registerNode(nodeJsonReport);
secureServer->registerNode(nodeUpdateFs);
secureServer->registerNode(nodeDeleteFs);
// secureServer->registerNode(nodeUpdateFs);
// secureServer->registerNode(nodeDeleteFs);
secureServer->registerNode(nodeAdmin);
secureServer->registerNode(nodeAdminFs);
// secureServer->registerNode(nodeAdminFs);
secureServer->registerNode(nodeAdminSettings);
secureServer->registerNode(nodeAdminSettingsApply);
secureServer->registerNode(nodeRoot); // This has to be last
@@ -181,10 +135,10 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
insecureServer->registerNode(nodeJsonFsBrowseStatic);
insecureServer->registerNode(nodeJsonDelete);
insecureServer->registerNode(nodeJsonReport);
insecureServer->registerNode(nodeUpdateFs);
insecureServer->registerNode(nodeDeleteFs);
// insecureServer->registerNode(nodeUpdateFs);
// insecureServer->registerNode(nodeDeleteFs);
insecureServer->registerNode(nodeAdmin);
insecureServer->registerNode(nodeAdminFs);
// insecureServer->registerNode(nodeAdminFs);
insecureServer->registerNode(nodeAdminSettings);
insecureServer->registerNode(nodeAdminSettingsApply);
insecureServer->registerNode(nodeRoot); // This has to be last
@@ -727,86 +681,6 @@ void handleHotspot(HTTPRequest *req, HTTPResponse *res)
res->println("<meta http-equiv=\"refresh\" content=\"0;url=/\" />\n");
}
void handleUpdateFs(HTTPRequest *req, HTTPResponse *res)
{
res->setHeader("Content-Type", "text/html");
res->setHeader("Access-Control-Allow-Origin", "*");
// res->setHeader("Access-Control-Allow-Methods", "POST");
res->println("<h1>Meshtastic</h1>\n");
res->println("Downloading Meshtastic Web Content...");
WiFiClientSecure *client = new WiFiClientSecure;
Stream *streamptr = getTarHTTPClientPtr(client, tarURL, certificate);
delay(5); // Let other network operations run
if (streamptr != nullptr) {
DEBUG_MSG("Connection to content server ... success!\n");
DEBUG_MSG("Deleting files from /static : \n");
htmlDeleteDir("/static");
delay(5); // Let other network operations run
TarUnpacker *TARUnpacker = new TarUnpacker();
TARUnpacker->haltOnError(false); // stop on fail (manual restart/reset required)
TARUnpacker->setTarVerify(false); // true = enables health checks but slows down the overall process
TARUnpacker->setupFSCallbacks(targzTotalBytesFn, targzFreeBytesFn); // prevent the partition from exploding, recommended
TARUnpacker->setLoggerCallback(BaseUnpacker::targzPrintLoggerCallback); // gz log verbosity
TARUnpacker->setTarProgressCallback(
BaseUnpacker::defaultProgressCallback); // prints the untarring progress for each individual file
TARUnpacker->setTarStatusProgressCallback(
BaseUnpacker::defaultTarStatusProgressCallback); // print the filenames as they're expanded
TARUnpacker->setTarMessageCallback(BaseUnpacker::targzPrintLoggerCallback); // tar log verbosity
String contentLengthStr = httpClient.header("Content-Length");
contentLengthStr.trim();
int64_t streamSize = -1;
if (contentLengthStr != "") {
streamSize = atoi(contentLengthStr.c_str());
Serial.printf("Stream size %d\n", streamSize);
res->printf("Stream size %d<br><br>\n", streamSize);
}
if (!TARUnpacker->tarStreamExpander(streamptr, streamSize, FSCom, "/static")) {
res->printf("tarStreamExpander failed with return code #%d\n", TARUnpacker->tarGzGetError());
Serial.printf("tarStreamExpander failed with return code #%d\n", TARUnpacker->tarGzGetError());
// Close the connection on error and free up memory
client->stop();
return;
} else {
/*
// print leftover bytes if any (probably zero-fill from the server)
while (httpClient.connected()) {
size_t streamSize = streamptr->available();
if (streamSize) {
Serial.printf("%02x ", streamptr->read());
} else
break;
}
*/
}
} else {
res->printf("Failed to establish http connection\n");
Serial.println("Failed to establish http connection");
return;
// Close the connection on error and free up memory
client->stop();
}
res->println("Done! Restarting the device. <a href=/>Click this in 10 seconds</a>");
/*
* This is a work around for a bug where we run out of memory.
* TODO: Fixme!
*/
// ESP.restart();
webServerThread->requestRestart = (millis() / 1000) + 5;
}
void handleDeleteFsContent(HTTPRequest *req, HTTPResponse *res)
{

View File

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

View File

@@ -1,4 +1,4 @@
[VERSION]
major = 1
minor = 3
build = 6
build = 8