mirror of
https://github.com/markqvist/reticulum-cpp.git
synced 2024-10-01 02:55:46 -04:00
WIP: Initial implementation of persistence
Persistence implemented with the help of the ArduinoJson library using MessagePack format.
This commit is contained in:
parent
c39e9e7fee
commit
f9a679ffc2
34
library.json
Normal file
34
library.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"name": "reticulum-cpp",
|
||||||
|
"version": "0.1.1",
|
||||||
|
"description": "Port of Reticulum Network Stack to C++ specifically but not exclusively targeting 32-bit and better MCUs",
|
||||||
|
"keywords": "reticulum, mcu, esp32",
|
||||||
|
"repository":
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/attermann/reticulum-cpp.git"
|
||||||
|
},
|
||||||
|
"authors":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Chad Attermann",
|
||||||
|
"email": "attermann@gmail.com",
|
||||||
|
"maintainer": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"homepage": "https://reticulum.network/",
|
||||||
|
"dependencies": {
|
||||||
|
"ArduinoJson": "~6.21.3",
|
||||||
|
"rweather/Crypto": "~0.4.0",
|
||||||
|
"sandeepmistry/LoRa": "~0.8.0",
|
||||||
|
"WiFi": "~2.0.0"
|
||||||
|
},
|
||||||
|
"frameworks": "*",
|
||||||
|
"platforms": "*",
|
||||||
|
"export": {},
|
||||||
|
"exclude": [
|
||||||
|
".github",
|
||||||
|
"src/main.cpp"
|
||||||
|
]
|
||||||
|
}
|
@ -23,6 +23,7 @@ build_flags =
|
|||||||
-Isrc
|
-Isrc
|
||||||
-DNATIVE
|
-DNATIVE
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
ArduinoJson@^6.21.3
|
||||||
rweather/Crypto@^0.4.0
|
rweather/Crypto@^0.4.0
|
||||||
lib_compat_mode = off
|
lib_compat_mode = off
|
||||||
|
|
||||||
@ -54,6 +55,7 @@ build_flags =
|
|||||||
-Wno-format
|
-Wno-format
|
||||||
-Isrc
|
-Isrc
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
ArduinoJson@^6.21.3
|
||||||
rweather/Crypto@^0.4.0
|
rweather/Crypto@^0.4.0
|
||||||
sandeepmistry/LoRa@^0.8.0
|
sandeepmistry/LoRa@^0.8.0
|
||||||
WiFi@^2.0.0
|
WiFi@^2.0.0
|
||||||
|
14
src/Bytes.h
14
src/Bytes.h
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -257,3 +259,15 @@ inline RNS::Bytes& operator << (RNS::Bytes& lhbytes, uint8_t rhbyte) {
|
|||||||
lhbytes.append(rhbyte);
|
lhbytes.append(rhbyte);
|
||||||
return lhbytes;
|
return lhbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
inline bool convertToJson(const RNS::Bytes& src, JsonVariant dst) {
|
||||||
|
return dst.set(src.toHex());
|
||||||
|
}
|
||||||
|
inline void convertFromJson(JsonVariantConst src, RNS::Bytes& dst) {
|
||||||
|
dst.assignHex(src.as<const char*>());
|
||||||
|
}
|
||||||
|
inline bool canConvertFromJson(JsonVariantConst src, const RNS::Bytes&) {
|
||||||
|
return src.is<const char*>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -36,16 +36,16 @@ void Identity::createKeys() {
|
|||||||
_object->_prv_bytes = _object->_prv->private_bytes();
|
_object->_prv_bytes = _object->_prv->private_bytes();
|
||||||
debug("Identity::createKeys: prv bytes: " + _object->_prv_bytes.toHex());
|
debug("Identity::createKeys: prv bytes: " + _object->_prv_bytes.toHex());
|
||||||
|
|
||||||
// CRYPTO: create encryption public keys
|
|
||||||
_object->_pub = _object->_prv->public_key();
|
|
||||||
_object->_pub_bytes = _object->_pub->public_bytes();
|
|
||||||
debug("Identity::createKeys: pub bytes: " + _object->_pub_bytes.toHex());
|
|
||||||
|
|
||||||
// CRYPTO: create signature private keys
|
// CRYPTO: create signature private keys
|
||||||
_object->_sig_prv = Cryptography::Ed25519PrivateKey::generate();
|
_object->_sig_prv = Cryptography::Ed25519PrivateKey::generate();
|
||||||
_object->_sig_prv_bytes = _object->_sig_prv->private_bytes();
|
_object->_sig_prv_bytes = _object->_sig_prv->private_bytes();
|
||||||
debug("Identity::createKeys: sig prv bytes: " + _object->_sig_prv_bytes.toHex());
|
debug("Identity::createKeys: sig prv bytes: " + _object->_sig_prv_bytes.toHex());
|
||||||
|
|
||||||
|
// CRYPTO: create encryption public keys
|
||||||
|
_object->_pub = _object->_prv->public_key();
|
||||||
|
_object->_pub_bytes = _object->_pub->public_bytes();
|
||||||
|
debug("Identity::createKeys: pub bytes: " + _object->_pub_bytes.toHex());
|
||||||
|
|
||||||
// CRYPTO: create signature public keys
|
// CRYPTO: create signature public keys
|
||||||
_object->_sig_pub = _object->_sig_prv->public_key();
|
_object->_sig_pub = _object->_sig_prv->public_key();
|
||||||
_object->_sig_pub_bytes = _object->_sig_pub->public_bytes();
|
_object->_sig_pub_bytes = _object->_sig_pub->public_bytes();
|
||||||
@ -127,20 +127,58 @@ void Identity::load_public_key(const Bytes& pub_bytes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Identity::load(const char* path) {
|
bool Identity::load(const char* path) {
|
||||||
/*
|
extreme("Reading identity key from storage...");
|
||||||
try:
|
try {
|
||||||
with open(path, "rb") as key_file:
|
Bytes prv_bytes = OS::read_file(path);
|
||||||
prv_bytes = key_file.read()
|
if (prv_bytes) {
|
||||||
return self.load_private_key(prv_bytes)
|
return load_private_key(prv_bytes);
|
||||||
return False
|
}
|
||||||
except Exception as e:
|
else {
|
||||||
RNS.log("Error while loading identity from "+str(path), RNS.LOG_ERROR)
|
return false;
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
}
|
||||||
*/
|
}
|
||||||
// MOCK
|
catch (std::exception& e) {
|
||||||
return true;
|
error("Error while loading identity from " + std::string(path));
|
||||||
|
error("The contained exception was: " + std::string(e.what()));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Saves the identity to a file. This will write the private key to disk,
|
||||||
|
and anyone with access to this file will be able to decrypt all
|
||||||
|
communication for the identity. Be very careful with this method.
|
||||||
|
|
||||||
|
:param path: The full path specifying where to save the identity.
|
||||||
|
:returns: True if the file was saved, otherwise False.
|
||||||
|
*/
|
||||||
|
bool Identity::to_file(const char* path) {
|
||||||
|
extreme("Writing identity key to storage...");
|
||||||
|
try {
|
||||||
|
return OS::write_file(get_private_key(), path);
|
||||||
|
}
|
||||||
|
catch (std::exception& e) {
|
||||||
|
error("Error while saving identity to " + std::string(path));
|
||||||
|
error("The contained exception was: " + std::string(e.what()));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create a new :ref:`RNS.Identity<api-identity>` instance from a file.
|
||||||
|
Can be used to load previously created and saved identities into Reticulum.
|
||||||
|
|
||||||
|
:param path: The full path to the saved :ref:`RNS.Identity<api-identity>` data
|
||||||
|
:returns: A :ref:`RNS.Identity<api-identity>` instance, or *None* if the loaded data was invalid.
|
||||||
|
*/
|
||||||
|
/*static*/ const Identity Identity::from_file(const char* path) {
|
||||||
|
Identity identity(false);
|
||||||
|
if (identity.load(path)) {
|
||||||
|
return identity;
|
||||||
|
}
|
||||||
|
return {Type::NONE};
|
||||||
|
}
|
||||||
|
|
||||||
/*static*/ void Identity::remember(const Bytes& packet_hash, const Bytes& destination_hash, const Bytes& public_key, const Bytes& app_data /*= {Bytes::NONE}*/) {
|
/*static*/ void Identity::remember(const Bytes& packet_hash, const Bytes& destination_hash, const Bytes& public_key, const Bytes& app_data /*= {Bytes::NONE}*/) {
|
||||||
if (public_key.size() != Type::Identity::KEYSIZE/8) {
|
if (public_key.size() != Type::Identity::KEYSIZE/8) {
|
||||||
|
@ -90,6 +90,7 @@ namespace RNS {
|
|||||||
_object->_hexhash = _object->_hash.toHex();
|
_object->_hexhash = _object->_hash.toHex();
|
||||||
};
|
};
|
||||||
bool load(const char* path);
|
bool load(const char* path);
|
||||||
|
bool to_file(const char* path);
|
||||||
|
|
||||||
inline const Bytes get_salt() const { assert(_object); return _object->_hash; }
|
inline const Bytes get_salt() const { assert(_object); return _object->_hash; }
|
||||||
inline const Bytes get_context() const { return {Bytes::NONE}; }
|
inline const Bytes get_context() const { return {Bytes::NONE}; }
|
||||||
@ -103,6 +104,7 @@ namespace RNS {
|
|||||||
void prove(const Packet& packet, const Destination& destination) const;
|
void prove(const Packet& packet, const Destination& destination) const;
|
||||||
void prove(const Packet& packet) const;
|
void prove(const Packet& packet) const;
|
||||||
|
|
||||||
|
static const Identity from_file(const char* path);
|
||||||
static void remember(const Bytes& packet_hash, const Bytes& destination_hash, const Bytes& public_key, const Bytes& app_data = {Bytes::NONE});
|
static void remember(const Bytes& packet_hash, const Bytes& destination_hash, const Bytes& public_key, const Bytes& app_data = {Bytes::NONE});
|
||||||
static Identity recall(const Bytes& destination_hash);
|
static Identity recall(const Bytes& destination_hash);
|
||||||
static Bytes recall_app_data(const Bytes& destination_hash);
|
static Bytes recall_app_data(const Bytes& destination_hash);
|
||||||
|
@ -73,3 +73,15 @@ void Interface::process_announce_queue() {
|
|||||||
RNS.log("The announce queue for this interface has been cleared.", RNS.LOG_ERROR)
|
RNS.log("The announce queue for this interface has been cleared.", RNS.LOG_ERROR)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ArduinoJson::convertFromJson(JsonVariantConst src, RNS::Interface& dst) {
|
||||||
|
if (!src.isNull()) {
|
||||||
|
RNS::Bytes hash;
|
||||||
|
hash.assignHex(src.as<const char*>());
|
||||||
|
// Query transport for matching interface
|
||||||
|
dst = Transport::find_interface_from_hash(hash);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dst = {RNS::Type::NONE};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -176,3 +176,16 @@ namespace RNS {
|
|||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
inline bool convertToJson(const RNS::Interface& src, JsonVariant dst) {
|
||||||
|
if (!src) {
|
||||||
|
return dst.set(nullptr);
|
||||||
|
}
|
||||||
|
return dst.set(src.get_hash().toHex());
|
||||||
|
}
|
||||||
|
void convertFromJson(JsonVariantConst src, RNS::Interface& dst);
|
||||||
|
inline bool canConvertFromJson(JsonVariantConst src, const RNS::Interface&) {
|
||||||
|
return src.is<const char*>() && strlen(src.as<const char*>()) == 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -554,3 +554,15 @@ void PacketReceipt::check_timeout() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ArduinoJson::convertFromJson(JsonVariantConst src, RNS::Packet& dst) {
|
||||||
|
if (!src.isNull()) {
|
||||||
|
RNS::Bytes hash;
|
||||||
|
hash.assignHex(src.as<const char*>());
|
||||||
|
// Query transport for matching interface
|
||||||
|
dst = Transport::get_cached_packet(hash);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dst = {RNS::Type::NONE};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
13
src/Packet.h
13
src/Packet.h
@ -274,3 +274,16 @@ namespace RNS {
|
|||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
inline bool convertToJson(const RNS::Packet& src, JsonVariant dst) {
|
||||||
|
if (!src) {
|
||||||
|
return dst.set(nullptr);
|
||||||
|
}
|
||||||
|
return dst.set(src.get_hash().toHex());
|
||||||
|
}
|
||||||
|
void convertFromJson(JsonVariantConst src, RNS::Packet& dst);
|
||||||
|
inline bool canConvertFromJson(JsonVariantConst src, const RNS::Packet&) {
|
||||||
|
return src.is<const char*>() && strlen(src.as<const char*>()) == 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "Transport.h"
|
#include "Transport.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Utilities/OS.h"
|
||||||
|
|
||||||
#include <RNG.h>
|
#include <RNG.h>
|
||||||
|
|
||||||
@ -13,6 +14,8 @@
|
|||||||
using namespace RNS;
|
using namespace RNS;
|
||||||
using namespace RNS::Type::Reticulum;
|
using namespace RNS::Type::Reticulum;
|
||||||
|
|
||||||
|
/*static*/ std::string Reticulum::storagepath;
|
||||||
|
|
||||||
/*static*/ bool Reticulum::__transport_enabled = false;
|
/*static*/ bool Reticulum::__transport_enabled = false;
|
||||||
/*static*/ bool Reticulum::__use_implicit_proof = true;
|
/*static*/ bool Reticulum::__use_implicit_proof = true;
|
||||||
/*static*/ bool Reticulum::__allow_probes = false;
|
/*static*/ bool Reticulum::__allow_probes = false;
|
||||||
@ -40,6 +43,8 @@ Reticulum::Reticulum() : _object(new Object()) {
|
|||||||
// CBA TEST Transport
|
// CBA TEST Transport
|
||||||
__transport_enabled = true;
|
__transport_enabled = true;
|
||||||
|
|
||||||
|
Utilities::OS::setup();
|
||||||
|
|
||||||
#ifdef ARDUINO
|
#ifdef ARDUINO
|
||||||
// Stir in the Ethernet MAC address.
|
// Stir in the Ethernet MAC address.
|
||||||
//byte mac[6];
|
//byte mac[6];
|
||||||
@ -51,9 +56,9 @@ Reticulum::Reticulum() : _object(new Object()) {
|
|||||||
//RNG.addNoiseSource(noise);
|
//RNG.addNoiseSource(noise);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
//z RNS.vendor.platformutils.platform_checks()
|
||||||
RNS.vendor.platformutils.platform_checks()
|
|
||||||
|
|
||||||
|
/* TODO
|
||||||
if configdir != None:
|
if configdir != None:
|
||||||
Reticulum.configdir = configdir
|
Reticulum.configdir = configdir
|
||||||
else:
|
else:
|
||||||
@ -73,7 +78,15 @@ Reticulum::Reticulum() : _object(new Object()) {
|
|||||||
Reticulum.cachepath = Reticulum.configdir+"/storage/cache"
|
Reticulum.cachepath = Reticulum.configdir+"/storage/cache"
|
||||||
Reticulum.resourcepath = Reticulum.configdir+"/storage/resources"
|
Reticulum.resourcepath = Reticulum.configdir+"/storage/resources"
|
||||||
Reticulum.identitypath = Reticulum.configdir+"/storage/identities"
|
Reticulum.identitypath = Reticulum.configdir+"/storage/identities"
|
||||||
|
*/
|
||||||
|
// CBA MOCK
|
||||||
|
#ifdef ARDUINO
|
||||||
|
storagepath = "";
|
||||||
|
#else
|
||||||
|
storagepath = ".";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* TODO
|
||||||
Reticulum.__transport_enabled = False
|
Reticulum.__transport_enabled = False
|
||||||
Reticulum.__use_implicit_proof = True
|
Reticulum.__use_implicit_proof = True
|
||||||
Reticulum.__allow_probes = False
|
Reticulum.__allow_probes = False
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "Type.h"
|
#include "Type.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -12,6 +13,19 @@ namespace RNS {
|
|||||||
class Reticulum {
|
class Reticulum {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
//z router = None
|
||||||
|
//z config = None
|
||||||
|
|
||||||
|
// The default configuration path will be expanded to a directory
|
||||||
|
// named ".reticulum" inside the current users home directory
|
||||||
|
//z userdir = os.path.expanduser("~")
|
||||||
|
//z configdir = None
|
||||||
|
//z configpath = ""
|
||||||
|
//p storagepath = ""
|
||||||
|
static std::string storagepath;
|
||||||
|
//z cachepath = ""
|
||||||
|
|
||||||
static bool __transport_enabled;
|
static bool __transport_enabled;
|
||||||
static bool __use_implicit_proof;
|
static bool __use_implicit_proof;
|
||||||
static bool __allow_probes;
|
static bool __allow_probes;
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#include "Test.h"
|
#include "Test.h"
|
||||||
|
|
||||||
#include "Log.h"
|
|
||||||
|
|
||||||
void test() {
|
void test() {
|
||||||
|
|
||||||
testOS();
|
testOS();
|
||||||
@ -9,5 +7,6 @@ void test() {
|
|||||||
testCollections();
|
testCollections();
|
||||||
testReference();
|
testReference();
|
||||||
testCrypto();
|
testCrypto();
|
||||||
|
testPersistence();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,3 +6,4 @@ void testBytes();
|
|||||||
void testCollections();
|
void testCollections();
|
||||||
void testReference();
|
void testReference();
|
||||||
void testCrypto();
|
void testCrypto();
|
||||||
|
void testPersistence();
|
||||||
|
502
src/Test/TestPersistence.cpp
Normal file
502
src/Test/TestPersistence.cpp
Normal file
@ -0,0 +1,502 @@
|
|||||||
|
//#include <unity.h>
|
||||||
|
|
||||||
|
#include "Transport.h"
|
||||||
|
#include "Interfaces/LoRaInterface.h"
|
||||||
|
#include "Utilities/Persistence.h"
|
||||||
|
#include "Utilities/OS.h"
|
||||||
|
#include "Log.h"
|
||||||
|
#include "Bytes.h"
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
public:
|
||||||
|
Test() {}
|
||||||
|
Test(const char* foo, const char* fee) : _foo(foo), _fee(fee) {}
|
||||||
|
const std::string toString() { return std::string("Test(") + _foo + "," + _fee + ")"; }
|
||||||
|
std::string _foo;
|
||||||
|
std::string _fee;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
template <>
|
||||||
|
struct Converter<Test> {
|
||||||
|
static bool toJson(const Test& src, JsonVariant dst) {
|
||||||
|
dst["foo"] = src._foo;
|
||||||
|
dst["fee"] = src._fee;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Test fromJson(JsonVariantConst src) {
|
||||||
|
return Test(src["foo"], src["fee"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool checkJson(JsonVariantConst src) {
|
||||||
|
return src["foo"].is<std::string>() && src["fee"].is<std::string>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ARDUINO
|
||||||
|
const char test_file_path[] = "/test_file";
|
||||||
|
#else
|
||||||
|
const char test_file_path[] = "test_file";
|
||||||
|
#endif
|
||||||
|
const char test_file_data[] = "test data";
|
||||||
|
|
||||||
|
void testWrite() {
|
||||||
|
RNS::Bytes data(test_file_data);
|
||||||
|
if (RNS::Utilities::OS::write_file(data, test_file_path)) {
|
||||||
|
RNS::extreme("wrote: " + std::to_string(data.size()) + " bytes");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("write failed");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void testRead() {
|
||||||
|
RNS::Bytes data = RNS::Utilities::OS::read_file(test_file_path);
|
||||||
|
if (data) {
|
||||||
|
RNS::extreme("read: " + std::to_string(data.size()) + " bytes");
|
||||||
|
RNS::extreme("data: " + data.toString());
|
||||||
|
assert(data.size() == strlen(test_file_data));
|
||||||
|
assert(memcmp(data.data(), test_file_data, strlen(test_file_data)) == 0);
|
||||||
|
//assert(RNS::Utilities::OS::remove_file(test_file_path));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("read failed");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ARDUINO
|
||||||
|
const char test_object_path[] = "/test_object";
|
||||||
|
#else
|
||||||
|
const char test_object_path[] = "test_object";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void testSerializeObject() {
|
||||||
|
|
||||||
|
Test test("bar", "fum");
|
||||||
|
|
||||||
|
StaticJsonDocument<1024> doc;
|
||||||
|
doc["foo"] = test._foo;
|
||||||
|
doc["fee"] = test._fee;
|
||||||
|
|
||||||
|
RNS::Bytes data;
|
||||||
|
size_t size = 1024;
|
||||||
|
//size_t length = serializeJson(doc, data.writable(size), size);
|
||||||
|
size_t length = serializeMsgPack(doc, data.writable(size), size);
|
||||||
|
if (length < size) {
|
||||||
|
data.resize(length);
|
||||||
|
}
|
||||||
|
RNS::extreme("serialized " + std::to_string(length) + " bytes");
|
||||||
|
if (length > 0) {
|
||||||
|
if (RNS::Utilities::OS::write_file(data, test_object_path)) {
|
||||||
|
RNS::extreme("wrote: " + std::to_string(data.size()) + " bytes");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("write failed");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("failed to serialize");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDeserializeObject() {
|
||||||
|
|
||||||
|
//StaticJsonDocument<8192> doc;
|
||||||
|
DynamicJsonDocument doc(8192);
|
||||||
|
|
||||||
|
RNS::Bytes data = RNS::Utilities::OS::read_file(test_object_path);
|
||||||
|
if (data) {
|
||||||
|
RNS::extreme("read: " + std::to_string(data.size()) + " bytes");
|
||||||
|
//RNS::extreme("data: " + data.toString());
|
||||||
|
//DeserializationError error = deserializeJson(doc, data.data());
|
||||||
|
DeserializationError error = deserializeMsgPack(doc, data.data());
|
||||||
|
if (!error) {
|
||||||
|
JsonObject root = doc.as<JsonObject>();
|
||||||
|
for (JsonPair kv : root) {
|
||||||
|
RNS::extreme("key: " + std::string(kv.key().c_str()) + " value: " + kv.value().as<const char*>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("failed to deserialize");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
//assert(RNS::Utilities::OS::remove_file(test_object_path));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("read failed");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ARDUINO
|
||||||
|
const char test_vector_path[] = "/test_vector";
|
||||||
|
#else
|
||||||
|
const char test_vector_path[] = "test_vector";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void testSerializeVector() {
|
||||||
|
|
||||||
|
//std::vector<std::string> vector;
|
||||||
|
//vector.push_back("foo");
|
||||||
|
//vector.push_back("bar");
|
||||||
|
std::vector<Test> vector;
|
||||||
|
vector.push_back({"bar1", "fum1"});
|
||||||
|
vector.push_back({"bar2", "fum2"});
|
||||||
|
|
||||||
|
StaticJsonDocument<4096> doc;
|
||||||
|
//copyArray(vector, doc.createNestedArray("vector"));
|
||||||
|
//doc["vector"] = vector;
|
||||||
|
//copyArray(vector, doc);
|
||||||
|
doc = vector;
|
||||||
|
|
||||||
|
/*
|
||||||
|
DynamicJsonBuffer jsonBuffer;
|
||||||
|
JsonObject& root = jsonBuffer.createObject();
|
||||||
|
|
||||||
|
//JsonObject& weather = root.createNestedObject("weather");
|
||||||
|
//weather["temperature"] = 12;
|
||||||
|
//weather["condition"] = "cloudy";
|
||||||
|
|
||||||
|
//JsonArray& coords = root.createNestedArray("coords");
|
||||||
|
//coords.add(48.7507371, 7);
|
||||||
|
//coords.add(2.2625587, 7);
|
||||||
|
JsonArray& arr = root.createNestedArray("vec");
|
||||||
|
for (auto entry : vec) {
|
||||||
|
arr.add(
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
RNS::Bytes data;
|
||||||
|
size_t size = 4096;
|
||||||
|
size_t length = serializeJson(doc, data.writable(size), size);
|
||||||
|
//size_t length = serializeMsgPack(doc, data.writable(size), size);
|
||||||
|
if (length < size) {
|
||||||
|
data.resize(length);
|
||||||
|
}
|
||||||
|
RNS::extreme("testSerializeVector: serialized " + std::to_string(length) + " bytes");
|
||||||
|
if (length > 0) {
|
||||||
|
if (RNS::Utilities::OS::write_file(data, test_vector_path)) {
|
||||||
|
RNS::extreme("testSerializeVector: wrote: " + std::to_string(data.size()) + " bytes");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("testSerializeVector: write failed");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("testSerializeVector: failed to serialize");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDeserializeVector() {
|
||||||
|
|
||||||
|
// Compute the required size
|
||||||
|
const int capacity =
|
||||||
|
JSON_ARRAY_SIZE(2) +
|
||||||
|
2*JSON_OBJECT_SIZE(3) +
|
||||||
|
4*JSON_OBJECT_SIZE(1);
|
||||||
|
|
||||||
|
//StaticJsonDocument<8192> doc;
|
||||||
|
DynamicJsonDocument doc(8192);
|
||||||
|
|
||||||
|
RNS::Bytes data = RNS::Utilities::OS::read_file(test_vector_path);
|
||||||
|
if (data) {
|
||||||
|
RNS::extreme("testDeserializeVector: read: " + std::to_string(data.size()) + " bytes");
|
||||||
|
//RNS::extreme("testDeserializeVector: data: " + data.toString());
|
||||||
|
DeserializationError error = deserializeJson(doc, data.data());
|
||||||
|
//DeserializationError error = deserializeMsgPack(doc, data.data());
|
||||||
|
if (!error) {
|
||||||
|
RNS::extreme("testDeserializeVector: successfully deserialized");
|
||||||
|
|
||||||
|
std::vector<Test> vector = doc.as<std::vector<Test>>();
|
||||||
|
for (auto& test : vector) {
|
||||||
|
RNS::extreme("testDeserializeVector: entry: " + test.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
//JsonArray arr = doc.as<JsonArray>();
|
||||||
|
//for (JsonVariant elem : arr) {
|
||||||
|
// RNS::extreme("testDeserializeVector: entry: " + elem.as<Test>().toString());
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("testDeserializeVector: failed to deserialize");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
//assert(RNS::Utilities::OS::remove_file(test_vector_path));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("testDeserializeVector: read failed");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ARDUINO
|
||||||
|
const char test_map_path[] = "/test_map";
|
||||||
|
#else
|
||||||
|
const char test_map_path[] = "test_map";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void testSerializeMap() {
|
||||||
|
|
||||||
|
//std::map<std::string, std::string> map;
|
||||||
|
//map.insert({"foo", "bar"});
|
||||||
|
//map.insert({"fee", "fum"});
|
||||||
|
std::map<std::string, Test> map;
|
||||||
|
map.insert({"one", {"bar1", "fum1"}});
|
||||||
|
map.insert({"two", {"bar2", "fum2"}});
|
||||||
|
|
||||||
|
StaticJsonDocument<4096> doc;
|
||||||
|
//copyArray(map, doc.createNestedArray("map"));
|
||||||
|
//doc["map"] = map;
|
||||||
|
//copyArray(map, doc);
|
||||||
|
doc = map;
|
||||||
|
|
||||||
|
RNS::Bytes data;
|
||||||
|
size_t size = 4096;
|
||||||
|
size_t length = serializeJson(doc, data.writable(size), size);
|
||||||
|
//size_t length = serializeMsgPack(doc, data.writable(size), size);
|
||||||
|
if (length < size) {
|
||||||
|
data.resize(length);
|
||||||
|
}
|
||||||
|
RNS::extreme("testSerializeMap: serialized " + std::to_string(length) + " bytes");
|
||||||
|
if (length > 0) {
|
||||||
|
if (RNS::Utilities::OS::write_file(data, test_map_path)) {
|
||||||
|
RNS::extreme("testSerializeMap: wrote: " + std::to_string(data.size()) + " bytes");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("testSerializeMap: write failed");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("testSerializeMap: failed to serialize");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDeserializeMap() {
|
||||||
|
|
||||||
|
// Compute the required size
|
||||||
|
const int capacity =
|
||||||
|
JSON_ARRAY_SIZE(2) +
|
||||||
|
2*JSON_OBJECT_SIZE(3) +
|
||||||
|
4*JSON_OBJECT_SIZE(1);
|
||||||
|
|
||||||
|
//StaticJsonDocument<8192> doc;
|
||||||
|
DynamicJsonDocument doc(8192);
|
||||||
|
|
||||||
|
RNS::Bytes data = RNS::Utilities::OS::read_file(test_map_path);
|
||||||
|
if (data) {
|
||||||
|
RNS::extreme("testDeserializeMap: read: " + std::to_string(data.size()) + " bytes");
|
||||||
|
//RNS::extreme("testDeserializeMap: data: " + data.toString());
|
||||||
|
DeserializationError error = deserializeJson(doc, data.data());
|
||||||
|
//DeserializationError error = deserializeMsgPack(doc, data.data());
|
||||||
|
if (!error) {
|
||||||
|
RNS::extreme("testDeserializeMap: successfully deserialized");
|
||||||
|
|
||||||
|
std::map<std::string, Test> map(doc.as<std::map<std::string, Test>>());
|
||||||
|
for (auto& [str, test] : map) {
|
||||||
|
RNS::extreme("testDeserializeMap: entry: " + str + " = " + test.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
//JsonObject root = doc.as<JsonObject>();
|
||||||
|
//for (JsonPair kv : root) {
|
||||||
|
// RNS::extreme("testDeserializeMap: entry: " + std::string(kv.key().c_str()) + " = " + kv.value().as<Test>().toString());
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("testDeserializeMap: failed to deserialize");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
//assert(RNS::Utilities::OS::remove_file(test_map_path));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("testDeserializeMap: testDeserializeVector: read failed");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ARDUINO
|
||||||
|
const char test_destination_table_path[] = "/test_destination_table";
|
||||||
|
#else
|
||||||
|
const char test_destination_table_path[] = "test_destination_table";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void testSerializeDestinationTable() {
|
||||||
|
|
||||||
|
//RNS::Bytes empty;
|
||||||
|
//std::set<RNS::Bytes> blobs;
|
||||||
|
//RNS::Interface interface({RNS::Type::NONE});
|
||||||
|
RNS::Interfaces::LoRaInterface lora_interface;
|
||||||
|
//RNS::Packet packet({RNS::Type::NONE});
|
||||||
|
static std::map<RNS::Bytes, RNS::Transport::DestinationEntry> map;
|
||||||
|
//DestinationEntry(double time, const Bytes& received_from, uint8_t announce_hops, double expires, const std::set<Bytes>& random_blobs, Interface& receiving_interface, const Packet& packet) :
|
||||||
|
//RNS::Transport::DestinationEntry entry_one(1.0, empty, 1, 0.0, blobs, interface, packet);
|
||||||
|
RNS::Bytes received;
|
||||||
|
received.assignHex("deadbeef");
|
||||||
|
RNS::Transport::DestinationEntry entry_one;
|
||||||
|
entry_one._timestamp = 1.0;
|
||||||
|
entry_one._received_from = received;
|
||||||
|
entry_one._receiving_interface = lora_interface;
|
||||||
|
RNS::Bytes one;
|
||||||
|
one.assignHex("1111111111111111");
|
||||||
|
map.insert({one, entry_one});
|
||||||
|
//RNS::Transport::DestinationEntry entry_two(2.0, empty, 1, 0.0, blobs, interface, packet);
|
||||||
|
RNS::Transport::DestinationEntry entry_two;
|
||||||
|
entry_two._timestamp = 2.0;
|
||||||
|
entry_two._received_from = received;
|
||||||
|
entry_two._receiving_interface = lora_interface;
|
||||||
|
RNS::Bytes two;
|
||||||
|
two.assignHex("2222222222222222");
|
||||||
|
map.insert({two, entry_two});
|
||||||
|
|
||||||
|
for (auto& [hash, test] : map) {
|
||||||
|
RNS::extreme("testSerializeDestinationTable: entry: " + hash.toHex() + " = (" + std::to_string(test._timestamp) + "," + test._received_from.toHex() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticJsonDocument<4096> doc;
|
||||||
|
doc = map;
|
||||||
|
|
||||||
|
RNS::Bytes data;
|
||||||
|
size_t size = 4096;
|
||||||
|
size_t length = serializeJson(doc, data.writable(size), size);
|
||||||
|
//size_t length = serializeMsgPack(doc, data.writable(size), size);
|
||||||
|
if (length < size) {
|
||||||
|
data.resize(length);
|
||||||
|
}
|
||||||
|
RNS::extreme("testSerializeDestinationTable: serialized " + std::to_string(length) + " bytes");
|
||||||
|
if (length > 0) {
|
||||||
|
if (RNS::Utilities::OS::write_file(data, test_destination_table_path)) {
|
||||||
|
RNS::extreme("testSerializeDestinationTable: wrote: " + std::to_string(data.size()) + " bytes");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("testSerializeDestinationTable: write failed");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("testSerializeDestinationTable: failed to serialize");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDeserializeDestinationTable() {
|
||||||
|
|
||||||
|
// Compute the required size
|
||||||
|
const int capacity =
|
||||||
|
JSON_ARRAY_SIZE(2) +
|
||||||
|
2*JSON_OBJECT_SIZE(3) +
|
||||||
|
4*JSON_OBJECT_SIZE(1);
|
||||||
|
|
||||||
|
//StaticJsonDocument<8192> doc;
|
||||||
|
DynamicJsonDocument doc(8192);
|
||||||
|
|
||||||
|
RNS::Bytes data = RNS::Utilities::OS::read_file(test_destination_table_path);
|
||||||
|
if (data) {
|
||||||
|
RNS::extreme("testDeserializeDestinationTable: read: " + std::to_string(data.size()) + " bytes");
|
||||||
|
//RNS::extreme("testDeserializeVector: data: " + data.toString());
|
||||||
|
DeserializationError error = deserializeJson(doc, data.data());
|
||||||
|
//DeserializationError error = deserializeMsgPack(doc, data.data());
|
||||||
|
if (!error) {
|
||||||
|
RNS::extreme("testDeserializeDestinationTable: successfully deserialized");
|
||||||
|
|
||||||
|
static std::map<RNS::Bytes, RNS::Transport::DestinationEntry> map(doc.as<std::map<RNS::Bytes, RNS::Transport::DestinationEntry>>());
|
||||||
|
for (auto& [hash, test] : map) {
|
||||||
|
RNS::extreme("testDeserializeDestinationTable: entry: " + hash.toHex() + " = (" + std::to_string(test._timestamp) + "," + test._received_from.toHex() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
//JsonObject root = doc.as<JsonObject>();
|
||||||
|
//for (JsonPair kv : root) {
|
||||||
|
// RNS::extreme("testDeserializeDestinationTable: entry: " + std::string(kv.key().c_str()) + " = " + kv.value().as<Test>().toString());
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("testDeserializeDestinationTable: failed to deserialize");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
//assert(RNS::Utilities::OS::remove_file(test_destination_table_path));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("testDeserializeDestinationTable: read failed");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testPersistence() {
|
||||||
|
RNS::head("Running testPersistence...", RNS::LOG_EXTREME);
|
||||||
|
testWrite();
|
||||||
|
testRead();
|
||||||
|
testSerializeObject();
|
||||||
|
testDeserializeObject();
|
||||||
|
testSerializeVector();
|
||||||
|
testDeserializeVector();
|
||||||
|
testSerializeMap();
|
||||||
|
testDeserializeMap();
|
||||||
|
testSerializeDestinationTable();
|
||||||
|
testDeserializeDestinationTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void setUp(void) {
|
||||||
|
// set stuff up here
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown(void) {
|
||||||
|
// clean stuff up here
|
||||||
|
}
|
||||||
|
|
||||||
|
int runUnityTests(void) {
|
||||||
|
UNITY_BEGIN();
|
||||||
|
RUN_TEST(testCollections);
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
// For native dev-platform or for some embedded frameworks
|
||||||
|
int main(void) {
|
||||||
|
return runUnityTests();
|
||||||
|
}
|
||||||
|
|
||||||
|
// For Arduino framework
|
||||||
|
void setup() {
|
||||||
|
// Wait ~2 seconds before the Unity test runner
|
||||||
|
// establishes connection with a board Serial interface
|
||||||
|
delay(2000);
|
||||||
|
|
||||||
|
runUnityTests();
|
||||||
|
}
|
||||||
|
void loop() {}
|
||||||
|
|
||||||
|
// For ESP-IDF framework
|
||||||
|
void app_main() {
|
||||||
|
runUnityTests();
|
||||||
|
}
|
||||||
|
*/
|
@ -81,15 +81,17 @@ using namespace RNS::Utilities;
|
|||||||
_owner = reticulum_instance;
|
_owner = reticulum_instance;
|
||||||
|
|
||||||
if (!_identity) {
|
if (!_identity) {
|
||||||
//z transport_identity_path = Reticulum::storagepath+"/transport_identity"
|
std::string transport_identity_path = Reticulum::storagepath + "/transport_identity";
|
||||||
//z if (os.path.isfile(transport_identity_path)) {
|
// CBA TEST
|
||||||
//z identity = Identity.from_file(transport_identity_path);
|
//OS::remove_file(transport_identity_path.c_str());
|
||||||
//z }
|
if (OS::file_exists(transport_identity_path.c_str())) {
|
||||||
|
_identity = Identity::from_file(transport_identity_path.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
if (!_identity) {
|
if (!_identity) {
|
||||||
verbose("No valid Transport Identity in storage, creating...");
|
verbose("No valid Transport Identity in storage, creating...");
|
||||||
_identity = new Identity();
|
_identity = Identity();
|
||||||
//z _identity.to_file(transport_identity_path);
|
_identity.to_file(transport_identity_path.c_str());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
verbose("Loaded Transport Identity from storage");
|
verbose("Loaded Transport Identity from storage");
|
||||||
@ -135,9 +137,8 @@ using namespace RNS::Utilities;
|
|||||||
// TODO
|
// TODO
|
||||||
/*
|
/*
|
||||||
if RNS.Reticulum.transport_enabled():
|
if RNS.Reticulum.transport_enabled():
|
||||||
destination_table_path = RNS.Reticulum.storagepath+"/destination_table"
|
|
||||||
tunnel_table_path = RNS.Reticulum.storagepath+"/tunnels"
|
|
||||||
|
|
||||||
|
destination_table_path = RNS.Reticulum.storagepath+"/destination_table"
|
||||||
if os.path.isfile(destination_table_path) and not Transport.owner.is_connected_to_shared_instance:
|
if os.path.isfile(destination_table_path) and not Transport.owner.is_connected_to_shared_instance:
|
||||||
serialised_destinations = []
|
serialised_destinations = []
|
||||||
try:
|
try:
|
||||||
@ -183,6 +184,7 @@ using namespace RNS::Utilities;
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not load destination table from storage, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Could not load destination table from storage, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
tunnel_table_path = RNS.Reticulum.storagepath+"/tunnels"
|
||||||
if os.path.isfile(tunnel_table_path) and not Transport.owner.is_connected_to_shared_instance:
|
if os.path.isfile(tunnel_table_path) and not Transport.owner.is_connected_to_shared_instance:
|
||||||
serialised_tunnels = []
|
serialised_tunnels = []
|
||||||
try:
|
try:
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include "Bytes.h"
|
#include "Bytes.h"
|
||||||
#include "Type.h"
|
#include "Type.h"
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
@ -54,11 +56,12 @@ namespace RNS {
|
|||||||
*/
|
*/
|
||||||
class Transport {
|
class Transport {
|
||||||
|
|
||||||
private:
|
public:
|
||||||
// CBA TODO Analyze safety of using Inrerface references here
|
// CBA TODO Analyze safety of using Inrerface references here
|
||||||
// CBA TODO Analyze safety of using Packet references here
|
// CBA TODO Analyze safety of using Packet references here
|
||||||
class DestinationEntry {
|
class DestinationEntry {
|
||||||
public:
|
public:
|
||||||
|
DestinationEntry() {}
|
||||||
DestinationEntry(double time, const Bytes& received_from, uint8_t announce_hops, double expires, const std::set<Bytes>& random_blobs, Interface& receiving_interface, const Packet& packet) :
|
DestinationEntry(double time, const Bytes& received_from, uint8_t announce_hops, double expires, const std::set<Bytes>& random_blobs, Interface& receiving_interface, const Packet& packet) :
|
||||||
_timestamp(time),
|
_timestamp(time),
|
||||||
_received_from(received_from),
|
_received_from(received_from),
|
||||||
@ -74,11 +77,11 @@ namespace RNS {
|
|||||||
Bytes _received_from;
|
Bytes _received_from;
|
||||||
uint8_t _hops = 0;
|
uint8_t _hops = 0;
|
||||||
double _expires = 0;
|
double _expires = 0;
|
||||||
std::set<Bytes> _random_blobs;
|
const std::set<Bytes> _random_blobs;
|
||||||
// CBA TODO does this need to be a reference in order for virtual method callbacks to work?
|
// CBA TODO does this need to be a reference in order for virtual method callbacks to work?
|
||||||
Interface& _receiving_interface;
|
Interface _receiving_interface = {Type::NONE};
|
||||||
//const Packet& _announce_packet;
|
//const Packet& _announce_packet;
|
||||||
Packet _announce_packet;
|
const Packet _announce_packet = {Type::NONE};
|
||||||
};
|
};
|
||||||
|
|
||||||
// CBA TODO Analyze safety of using Inrerface references here
|
// CBA TODO Analyze safety of using Inrerface references here
|
||||||
@ -101,17 +104,17 @@ namespace RNS {
|
|||||||
double _timestamp = 0;
|
double _timestamp = 0;
|
||||||
double _retransmit_timeout = 0;
|
double _retransmit_timeout = 0;
|
||||||
uint8_t _retries = 0;
|
uint8_t _retries = 0;
|
||||||
Bytes _received_from;
|
const Bytes _received_from;
|
||||||
uint8_t _hops = 0;
|
uint8_t _hops = 0;
|
||||||
// CBA Storing packet reference causes memory issues, presumably because orignal packet is being destroyed
|
// CBA Storing packet reference causes memory issues, presumably because orignal packet is being destroyed
|
||||||
// MUST use instance instad of reference!!!
|
// MUST use instance instad of reference!!!
|
||||||
//const Packet& _packet;
|
//const Packet& _packet;
|
||||||
Packet _packet;
|
const Packet _packet = {Type::NONE};
|
||||||
uint8_t _local_rebroadcasts = 0;
|
uint8_t _local_rebroadcasts = 0;
|
||||||
bool _block_rebroadcasts = false;
|
bool _block_rebroadcasts = false;
|
||||||
// CBA TODO does this need to be a reference in order for virtual method callbacks to work?
|
// CBA TODO does this need to be a reference in order for virtual method callbacks to work?
|
||||||
//const Interface& _attached_interface;
|
//const Interface& _attached_interface;
|
||||||
Interface _attached_interface;
|
const Interface _attached_interface = {Type::NONE};
|
||||||
};
|
};
|
||||||
|
|
||||||
// CBA TODO Analyze safety of using Inrerface references here
|
// CBA TODO Analyze safety of using Inrerface references here
|
||||||
@ -131,16 +134,16 @@ namespace RNS {
|
|||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
double _timestamp = 0;
|
double _timestamp = 0;
|
||||||
Bytes _next_hop;
|
const Bytes _next_hop;
|
||||||
// CBA TODO does this need to be a reference in order for virtual method callbacks to work?
|
// CBA TODO does this need to be a reference in order for virtual method callbacks to work?
|
||||||
//const Interface& _outbound_interface;
|
//const Interface& _outbound_interface;
|
||||||
Interface _outbound_interface;
|
const Interface _outbound_interface = {Type::NONE};
|
||||||
uint8_t _remaining_hops = 0;
|
uint8_t _remaining_hops = 0;
|
||||||
// CBA TODO does this need to be a reference in order for virtual method callbacks to work?
|
// CBA TODO does this need to be a reference in order for virtual method callbacks to work?
|
||||||
//const Interface& _receiving_interface;
|
//const Interface& _receiving_interface;
|
||||||
Interface _receiving_interface;
|
const Interface _receiving_interface = {Type::NONE};
|
||||||
uint8_t _hops = 0;
|
uint8_t _hops = 0;
|
||||||
Bytes _destination_hash;
|
const Bytes _destination_hash;
|
||||||
bool _validated = false;
|
bool _validated = false;
|
||||||
double _proof_timeout = 0;
|
double _proof_timeout = 0;
|
||||||
};
|
};
|
||||||
@ -157,10 +160,10 @@ namespace RNS {
|
|||||||
public:
|
public:
|
||||||
// CBA TODO does this need to be a reference in order for virtual method callbacks to work?
|
// CBA TODO does this need to be a reference in order for virtual method callbacks to work?
|
||||||
//const Interface& _receiving_interface;
|
//const Interface& _receiving_interface;
|
||||||
Interface _receiving_interface;
|
const Interface _receiving_interface = {Type::NONE};
|
||||||
// CBA TODO does this need to be a reference in order for virtual method callbacks to work?
|
// CBA TODO does this need to be a reference in order for virtual method callbacks to work?
|
||||||
//const Interface& _outbound_interface;
|
//const Interface& _outbound_interface;
|
||||||
Interface _outbound_interface;
|
const Interface _outbound_interface = {Type::NONE};
|
||||||
double _timestamp = 0;
|
double _timestamp = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -174,11 +177,11 @@ namespace RNS {
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
Bytes _destination_hash;
|
const Bytes _destination_hash;
|
||||||
double _timeout = 0;
|
double _timeout = 0;
|
||||||
// CBA TODO does this need to be a reference in order for virtual method callbacks to work?
|
// CBA TODO does this need to be a reference in order for virtual method callbacks to work?
|
||||||
//const Interface& _requesting_interface;
|
//const Interface& _requesting_interface;
|
||||||
Interface _requesting_interface;
|
const Interface _requesting_interface = {Type::NONE};
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -312,4 +315,55 @@ namespace RNS {
|
|||||||
static Identity _identity;
|
static Identity _identity;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
|
||||||
|
// ArduinoJSON serialization support for RNS::Transport::DestinationEntry
|
||||||
|
template <>
|
||||||
|
struct Converter<RNS::Transport::DestinationEntry> {
|
||||||
|
static bool toJson(const RNS::Transport::DestinationEntry& src, JsonVariant dst) {
|
||||||
|
dst["timestamp"] = src._timestamp;
|
||||||
|
dst["received_from"] = src._received_from;
|
||||||
|
dst["announce_hops"] = src._hops;
|
||||||
|
dst["expires"] = src._expires;
|
||||||
|
//dst["random_blobs"] = src._random_blobs;
|
||||||
|
dst["receiving_interface"] = src._receiving_interface;
|
||||||
|
dst["packet"] = src._announce_packet;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static RNS::Transport::DestinationEntry fromJson(JsonVariantConst src) {
|
||||||
|
/**/
|
||||||
|
RNS::Transport::DestinationEntry dst;
|
||||||
|
dst._timestamp = src["timestamp"];
|
||||||
|
dst._received_from = src["received_from"];
|
||||||
|
dst._hops = src["announce_hops"];
|
||||||
|
dst._expires = src["expires"];
|
||||||
|
//dst._random_blobs = src["random_blobs"];
|
||||||
|
dst._receiving_interface = src["receiving_interface"];
|
||||||
|
//dst._announce_packet = src["packet"];
|
||||||
|
/**/
|
||||||
|
/*
|
||||||
|
//RNS::Transport::DestinationEntry dst(src["timestamp"], src["received_from"], src["announce_hops"], src["expires"], src["random_blobs"], src["receiving_interface"], src["packet"]);
|
||||||
|
RNS::Transport::DestinationEntry dst(
|
||||||
|
src["timestamp"].as<double>(),
|
||||||
|
src["received_from"].as<RNS::Bytes>(),
|
||||||
|
src["announce_hops"].as<int>(),
|
||||||
|
src["expires"].as<double>(),
|
||||||
|
src["random_blobs"].as<std::set<RNS::Bytes>>(),
|
||||||
|
src["receiving_interface"].as<RNS::Interface>(),
|
||||||
|
src["packet"].as<RNS::Packet>()
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
static bool checkJson(JsonVariantConst src) {
|
||||||
|
return
|
||||||
|
src["timestamp"].is<double>() &&
|
||||||
|
src["received_from"].is<RNS::Bytes>() &&
|
||||||
|
src["announce_hops"].is<int>() &&
|
||||||
|
src["expires"].is<double>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
144
src/Utilities/OS.cpp
Normal file
144
src/Utilities/OS.cpp
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#include "OS.h"
|
||||||
|
|
||||||
|
#include "../Log.h"
|
||||||
|
|
||||||
|
#ifdef ARDUINO
|
||||||
|
#include <FS.h>
|
||||||
|
#include <LittleFS.h>
|
||||||
|
#else
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace RNS;
|
||||||
|
using namespace RNS::Utilities;
|
||||||
|
|
||||||
|
/*static*/ void OS::setup() {
|
||||||
|
|
||||||
|
#ifdef ARDUINO
|
||||||
|
// Setup filesystem
|
||||||
|
if (!LittleFS.begin(true)){
|
||||||
|
Serial.println("LittleFS Mount Failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ bool OS::file_exists(const char* file_path) {
|
||||||
|
#ifdef ARDUINO
|
||||||
|
File file = LittleFS.open(file_path, FILE_READ);
|
||||||
|
if (file) {
|
||||||
|
#else
|
||||||
|
FILE* file = fopen(file_path, "r");
|
||||||
|
if (file != nullptr) {
|
||||||
|
#endif
|
||||||
|
//RNS::extreme("file_exists: file exists, closing file");
|
||||||
|
#ifdef ARDUINO
|
||||||
|
file.close();
|
||||||
|
#else
|
||||||
|
fclose(file);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("file_exists: failed to open file " + std::string(file_path));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ const Bytes OS::read_file(const char* file_path) {
|
||||||
|
Bytes data;
|
||||||
|
#ifdef ARDUINO
|
||||||
|
File file = LittleFS.open(file_path, FILE_READ);
|
||||||
|
if (file) {
|
||||||
|
size_t size = file.size();
|
||||||
|
size_t read = file.readBytes((char*)data.writable(size), size);
|
||||||
|
#else
|
||||||
|
FILE* file = fopen(file_path, "r");
|
||||||
|
if (file != nullptr) {
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
size_t size = ftell(file);
|
||||||
|
rewind(file);
|
||||||
|
//size_t read = fread(data.writable(size), size, 1, file);
|
||||||
|
size_t read = fread(data.writable(size), 1, size, file);
|
||||||
|
#endif
|
||||||
|
RNS::extreme("read_file: read " + std::to_string(read) + " bytes from file " + std::string(file_path));
|
||||||
|
if (read != size) {
|
||||||
|
RNS::extreme("read_file: failed to read file " + std::string(file_path));
|
||||||
|
data.clear();
|
||||||
|
}
|
||||||
|
//RNS::extreme("read_file: closing input file");
|
||||||
|
#ifdef ARDUINO
|
||||||
|
file.close();
|
||||||
|
#else
|
||||||
|
fclose(file);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("read_file: failed to open input file " + std::string(file_path));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ bool OS::write_file(const Bytes& data, const char* file_path) {
|
||||||
|
bool success = false;
|
||||||
|
#ifdef ARDUINO
|
||||||
|
File file = LittleFS.open(file_path, FILE_WRITE);
|
||||||
|
if (file) {
|
||||||
|
size_t wrote = file.write(data.data(), data.size());
|
||||||
|
#else
|
||||||
|
FILE* file = fopen(file_path, "w");
|
||||||
|
if (file != nullptr) {
|
||||||
|
//size_t wrote = fwrite(data.data(), data.size(), 1, file);
|
||||||
|
size_t wrote = fwrite(data.data(), 1, data.size(), file);
|
||||||
|
#endif
|
||||||
|
RNS::extreme("write_file: wrote " + std::to_string(wrote) + " bytes to file " + std::string(file_path));
|
||||||
|
if (wrote == data.size()) {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("write_file: failed to write file " + std::string(file_path));
|
||||||
|
}
|
||||||
|
//RNS::extreme("write_file: closing output file");
|
||||||
|
#ifdef ARDUINO
|
||||||
|
file.close();
|
||||||
|
#else
|
||||||
|
fclose(file);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RNS::extreme("write_file: failed to open output file " + std::string(file_path));
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ bool OS::remove_file(const char* file_path) {
|
||||||
|
#ifdef ARDUINO
|
||||||
|
return LittleFS.remove(file_path);
|
||||||
|
#else
|
||||||
|
return (remove(file_path) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ bool OS::rename_file(const char* from_file_path, const char* to_file_path) {
|
||||||
|
#ifdef ARDUINO
|
||||||
|
return LittleFS.rename(from_file_path, to_file_path);
|
||||||
|
#else
|
||||||
|
return (rename(from_file_path, to_file_path) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ bool OS::create_directory(const char* directory_path) {
|
||||||
|
#ifdef ARDUINO
|
||||||
|
return LittleFS.mkdir(directory_path);
|
||||||
|
#else
|
||||||
|
struct stat st = {0};
|
||||||
|
if (stat(directory_path, &st) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return (mkdir(directory_path, 0700) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
@ -1,16 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Bytes.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#ifdef ARDUINO
|
||||||
|
#include "Arduino.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace RNS { namespace Utilities {
|
namespace RNS { namespace Utilities {
|
||||||
|
|
||||||
class OS {
|
class OS {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static void setup();
|
||||||
|
|
||||||
// sleep for specified milliseconds
|
// sleep for specified milliseconds
|
||||||
//static inline void sleep(float seconds) { ::sleep(seconds); }
|
//static inline void sleep(float seconds) { ::sleep(seconds); }
|
||||||
#ifdef ARDUINO
|
#ifdef ARDUINO
|
||||||
@ -30,6 +38,13 @@ namespace RNS { namespace Utilities {
|
|||||||
//static inline float round(float value, uint8_t precision) { return std::round(value / precision) * precision; }
|
//static inline float round(float value, uint8_t precision) { return std::round(value / precision) * precision; }
|
||||||
static inline double round(double value, uint8_t precision) { return std::round(value / precision) * precision; }
|
static inline double round(double value, uint8_t precision) { return std::round(value / precision) * precision; }
|
||||||
|
|
||||||
|
static bool file_exists(const char* file_path);
|
||||||
|
static const RNS::Bytes read_file(const char* file_path);
|
||||||
|
static bool write_file(const RNS::Bytes& data, const char* file_path);
|
||||||
|
static bool remove_file(const char* file_path);
|
||||||
|
static bool rename_file(const char* from_file_path, const char* to_file_path);
|
||||||
|
static bool create_directory(const char* directory_path);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
89
src/Utilities/Persistence.h
Normal file
89
src/Utilities/Persistence.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
|
||||||
|
#include "Bytes.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
|
||||||
|
// ArduinoJSON serialization support for std::vector<T>
|
||||||
|
template <typename T>
|
||||||
|
struct Converter<std::vector<T> > {
|
||||||
|
static void toJson(const std::vector<T>& src, JsonVariant dst) {
|
||||||
|
JsonArray array = dst.to<JsonArray>();
|
||||||
|
for (T item : src)
|
||||||
|
array.add(item);
|
||||||
|
}
|
||||||
|
static std::vector<T> fromJson(JsonVariantConst src) {
|
||||||
|
std::vector<T> dst;
|
||||||
|
for (T item : src.as<JsonArrayConst>())
|
||||||
|
dst.push_back(item);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
static bool checkJson(JsonVariantConst src) {
|
||||||
|
JsonArrayConst array = src;
|
||||||
|
bool result = array;
|
||||||
|
for (JsonVariantConst item : array)
|
||||||
|
result &= item.is<T>();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ArduinoJSON serialization support for std::map<std::string, T>
|
||||||
|
template <typename T>
|
||||||
|
struct Converter<std::map<std::string, T> > {
|
||||||
|
static void toJson(const std::map<std::string, T>& src, JsonVariant dst) {
|
||||||
|
JsonObject obj = dst.to<JsonObject>();
|
||||||
|
for (const auto& item : src)
|
||||||
|
obj[item.first] = item.second;
|
||||||
|
}
|
||||||
|
static std::map<std::string, T> fromJson(JsonVariantConst src) {
|
||||||
|
std::map<std::string, T> dst;
|
||||||
|
for (JsonPairConst item : src.as<JsonObjectConst>())
|
||||||
|
dst[item.key().c_str()] = item.value().as<T>();
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
static bool checkJson(JsonVariantConst src) {
|
||||||
|
JsonObjectConst obj = src;
|
||||||
|
bool result = obj;
|
||||||
|
for (JsonPairConst item : obj)
|
||||||
|
result &= item.value().is<T>();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ArduinoJSON serialization support for std::map<Bytes, T>
|
||||||
|
template <typename T>
|
||||||
|
struct Converter<std::map<RNS::Bytes, T> > {
|
||||||
|
static void toJson(const std::map<RNS::Bytes, T>& src, JsonVariant dst) {
|
||||||
|
JsonObject obj = dst.to<JsonObject>();
|
||||||
|
for (const auto& item : src) {
|
||||||
|
//obj[item.first] = item.second;
|
||||||
|
obj[item.first.toHex()] = item.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static std::map<RNS::Bytes, T> fromJson(JsonVariantConst src) {
|
||||||
|
std::map<RNS::Bytes, T> dst;
|
||||||
|
for (JsonPairConst item : src.as<JsonObjectConst>()) {
|
||||||
|
//dst[item.key().c_str()] = item.value().as<T>();
|
||||||
|
RNS::Bytes key;
|
||||||
|
key.assignHex(item.key().c_str());
|
||||||
|
//dst[key] = item.value().as<T>();
|
||||||
|
dst.insert({key, item.value().as<T>()});
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
static bool checkJson(JsonVariantConst src) {
|
||||||
|
JsonObjectConst obj = src;
|
||||||
|
bool result = obj;
|
||||||
|
for (JsonPairConst item : obj) {
|
||||||
|
result &= item.value().is<T>();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
22
src/main.cpp
22
src/main.cpp
@ -120,9 +120,10 @@ void run_tests() {
|
|||||||
RNS::LogLevel loglevel = RNS::loglevel();
|
RNS::LogLevel loglevel = RNS::loglevel();
|
||||||
//RNS::loglevel(RNS::LOG_WARNING);
|
//RNS::loglevel(RNS::LOG_WARNING);
|
||||||
RNS::loglevel(RNS::LOG_EXTREME);
|
RNS::loglevel(RNS::LOG_EXTREME);
|
||||||
test();
|
//test();
|
||||||
//testReference();
|
//testReference();
|
||||||
//testCrypto();
|
//testCrypto();
|
||||||
|
testPersistence();
|
||||||
RNS::loglevel(loglevel);
|
RNS::loglevel(loglevel);
|
||||||
RNS::extreme("Finished running tests");
|
RNS::extreme("Finished running tests");
|
||||||
//return;
|
//return;
|
||||||
@ -134,6 +135,7 @@ void run_tests() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(RUN_RETICULUM)
|
||||||
void reticulum_announce() {
|
void reticulum_announce() {
|
||||||
if (destination) {
|
if (destination) {
|
||||||
RNS::head("Announcing destination...", RNS::LOG_EXTREME);
|
RNS::head("Announcing destination...", RNS::LOG_EXTREME);
|
||||||
@ -145,8 +147,7 @@ void reticulum_announce() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(RUN_RETICULUM)
|
void reticulum_setup() {
|
||||||
void setup_reticulum() {
|
|
||||||
RNS::info("Setting up Reticulum...");
|
RNS::info("Setting up Reticulum...");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -177,7 +178,7 @@ void setup_reticulum() {
|
|||||||
|
|
||||||
#ifdef UDP_INTERFACE
|
#ifdef UDP_INTERFACE
|
||||||
RNS::head("Starting UDPInterface...", RNS::LOG_EXTREME);
|
RNS::head("Starting UDPInterface...", RNS::LOG_EXTREME);
|
||||||
udp_interface.start("some_ssid", "some_password", 2424);
|
udp_interface.start("some_ssid", "some_password");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LORA_INTERFACE
|
#ifdef LORA_INTERFACE
|
||||||
@ -251,13 +252,14 @@ void setup_reticulum() {
|
|||||||
destination.receive(recv_packet);
|
destination.receive(recv_packet);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
RNS::head("Ready!", RNS::LOG_EXTREME);
|
||||||
}
|
}
|
||||||
catch (std::exception& e) {
|
catch (std::exception& e) {
|
||||||
RNS::error(std::string("!!! Exception in setup_reticulum: ") + e.what() + " !!!");
|
RNS::error(std::string("!!! Exception in reticulum_setup: ") + e.what() + " !!!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void teardown_reticulum() {
|
void reticulum_teardown() {
|
||||||
RNS::info("Tearing down Reticulum...");
|
RNS::info("Tearing down Reticulum...");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -275,7 +277,7 @@ void teardown_reticulum() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
catch (std::exception& e) {
|
catch (std::exception& e) {
|
||||||
RNS::error(std::string("!!! Exception in teardown_reticulum: ") + e.what() + " !!!");
|
RNS::error(std::string("!!! Exception in reticulum_teardown: ") + e.what() + " !!!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -317,11 +319,11 @@ void setup() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(RUN_RETICULUM)
|
#if defined(RUN_RETICULUM)
|
||||||
setup_reticulum();
|
reticulum_setup();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARDUINO
|
#ifdef ARDUINO
|
||||||
Serial.print("Goodbye from T-Beam on PlatformIO!\n");
|
//Serial.print("Goodbye from T-Beam on PlatformIO!\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,7 +382,9 @@ int main(void) {
|
|||||||
if (ch > 0) {
|
if (ch > 0) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'a':
|
case 'a':
|
||||||
|
#if defined(RUN_RETICULUM)
|
||||||
reticulum_announce();
|
reticulum_announce();
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
run = false;
|
run = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user