From 0db15db625a3c05ac4f1a27e591af7c3459fc439 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Mon, 17 Feb 2025 19:22:31 +1100 Subject: [PATCH 01/28] * new Packet type: PAYLOAD_TYPE_TRACE --- examples/companion_radio/main.cpp | 4 ++ examples/simple_secure_chat/main.cpp | 4 ++ src/Dispatcher.cpp | 5 ++- src/Mesh.cpp | 43 +++++++++++++++++-- src/Mesh.h | 10 +++++ src/Packet.cpp | 7 +++- src/Packet.h | 4 ++ src/helpers/BaseChatMesh.cpp | 63 ++++++++++++++++++++++++++++ src/helpers/BaseChatMesh.h | 3 ++ 9 files changed, 135 insertions(+), 8 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index af677537..842abdb3 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -448,6 +448,10 @@ protected: // TODO: check for Get Stats response } + void onContactTraceRecv(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t hash[], int8_t snr[], uint8_t path_len) override { + // TODO: write an out_frame + } + uint32_t calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const override { return SEND_TIMEOUT_BASE_MILLIS + (FLOOD_SEND_TIMEOUT_FACTOR * pkt_airtime_millis); } diff --git a/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index 7d589828..0483eaf1 100644 --- a/examples/simple_secure_chat/main.cpp +++ b/examples/simple_secure_chat/main.cpp @@ -268,6 +268,10 @@ protected: // not supported } + void onContactTraceRecv(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t hash[], int8_t snr[], uint8_t path_len) override { + // TODO: write an out_frame + } + uint32_t calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const override { return SEND_TIMEOUT_BASE_MILLIS + (FLOOD_SEND_TIMEOUT_FACTOR * pkt_airtime_millis); } diff --git a/src/Dispatcher.cpp b/src/Dispatcher.cpp index 81822baf..fa1895bd 100644 --- a/src/Dispatcher.cpp +++ b/src/Dispatcher.cpp @@ -105,7 +105,7 @@ void Dispatcher::checkRecv() { pkt->payload_len = len - i; // payload is remainder memcpy(pkt->payload, &raw[i], pkt->payload_len); - score = _radio->packetScore(_radio->getLastSNR(), len); + score = _radio->packetScore(pkt->_snr = _radio->getLastSNR(), len); air_time = _radio->getEstAirtimeFor(len); } } @@ -117,7 +117,7 @@ void Dispatcher::checkRecv() { #if MESH_PACKET_LOGGING Serial.printf("PACKET: recv, len=%d (type=%d, route=%s, payload_len=%d) SNR=%d RSSI=%d score=%d\n", 2 + pkt->path_len + pkt->payload_len, pkt->getPayloadType(), pkt->isRouteDirect() ? "D" : "F", pkt->payload_len, - (int)_radio->getLastSNR(), (int)_radio->getLastRSSI(), (int)(score*1000)); + (int)pkt->getSNR(), (int)_radio->getLastRSSI(), (int)(score*1000)); #endif if (pkt->isRouteFlood()) { @@ -198,6 +198,7 @@ Packet* Dispatcher::obtainNewPacket() { n_full_events++; } else { pkt->payload_len = pkt->path_len = 0; + pkt->_snr = 0; } return pkt; } diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 96092f30..8980e6aa 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -41,6 +41,16 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { // remove our hash from 'path', then re-broadcast pkt->path_len -= PATH_HASH_SIZE; memcpy(pkt->path, &pkt->path[PATH_HASH_SIZE], pkt->path_len); + + if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE && pkt->payload_len + PATH_HASH_SIZE+1 < MAX_PACKET_PAYLOAD) { + if ((pkt->payload[0] & 3) == 0) { + // append our hash + SNR + pkt->payload_len += self_id.copyHashTo(&pkt->payload[pkt->payload_len]); + pkt->payload[pkt->payload_len++] = (int8_t) (pkt->getSNR()*4); + } else { + // unknown flags:type, don't append any info + } + } return ACTION_RETRANSMIT(0); // Routed traffic is HIGHEST priority (and NO per-hop delay) } return ACTION_RELEASE; // this node is NOT the next hop (OR this packet has already been forwarded), so discard. @@ -61,16 +71,21 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { } break; } + case PAYLOAD_TYPE_TRACE: case PAYLOAD_TYPE_PATH: case PAYLOAD_TYPE_REQ: case PAYLOAD_TYPE_RESPONSE: case PAYLOAD_TYPE_TXT_MSG: { int i = 0; + if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) { + //uint8_t flags = pkt->payload[i]; // reserved for now + i++; // skip over + } uint8_t dest_hash = pkt->payload[i++]; uint8_t src_hash = pkt->payload[i++]; uint8_t* macAndData = &pkt->payload[i]; // MAC + encrypted data - if (i + 2 >= pkt->payload_len) { + if (i + CIPHER_MAC_SIZE >= pkt->payload_len) { MESH_DEBUG_PRINTLN("Mesh::onRecvPacket(): incomplete data packet"); } else if (!_tables->hasSeen(pkt)) { // NOTE: this is a 'first packet wins' impl. When receiving from multiple paths, the first to arrive wins. @@ -88,7 +103,12 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { // decrypt, checking MAC is valid uint8_t data[MAX_PACKET_PAYLOAD]; - int len = Utils::MACThenDecrypt(secret, data, macAndData, pkt->payload_len - i); + int len; + if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) { + len = Utils::MACThenDecrypt(secret, data, macAndData, CIPHER_MAC_SIZE+CIPHER_BLOCK_SIZE); // encrypted part is fixed-len + } else { + len = Utils::MACThenDecrypt(secret, data, macAndData, pkt->payload_len - i); + } if (len > 0) { // success! if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH) { int k = 0; @@ -104,6 +124,8 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { if (rpath) sendDirect(rpath, path, path_len); } } + } else if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) { + onPeerTraceRecv(pkt, j, secret, data); } else { onPeerDataRecv(pkt, pkt->getPayloadType(), j, secret, data, len); } @@ -227,6 +249,16 @@ DispatcherAction Mesh::routeRecvPacket(Packet* packet) { // append this node's hash to 'path' packet->path_len += self_id.copyHashTo(&packet->path[packet->path_len]); + if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE && (packet->payload[0] & 3) != 0) { + // flags:type must be zero (otherwise, some future/unknown sub-type) + return ACTION_RELEASE; // don't forward, just discard + } + + if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE && packet->payload_len + 1 < MAX_PACKET_PAYLOAD) { + // append packet SNR + packet->payload[packet->payload_len++] = (int8_t) (packet->getSNR()*4); + } + uint32_t d = getRetransmitDelay(packet); // as this propagates outwards, give it lower and lower priority return ACTION_RETRANSMIT_DELAYED(packet->path_len, d); // give priority to closer sources, than ones further away @@ -316,8 +348,8 @@ Packet* Mesh::createPathReturn(const uint8_t* dest_hash, const uint8_t* secret, } Packet* Mesh::createDatagram(uint8_t type, const Identity& dest, const uint8_t* secret, const uint8_t* data, size_t data_len) { - if (type == PAYLOAD_TYPE_TXT_MSG || type == PAYLOAD_TYPE_REQ || type == PAYLOAD_TYPE_RESPONSE) { - if (data_len + 2 + CIPHER_BLOCK_SIZE-1 > MAX_PACKET_PAYLOAD) return NULL; + if (type == PAYLOAD_TYPE_TXT_MSG || type == PAYLOAD_TYPE_REQ || type == PAYLOAD_TYPE_RESPONSE || type == PAYLOAD_TYPE_TRACE) { + if (data_len + CIPHER_MAC_SIZE + CIPHER_BLOCK_SIZE-1 > MAX_PACKET_PAYLOAD) return NULL; } else { return NULL; // invalid type } @@ -330,6 +362,9 @@ Packet* Mesh::createDatagram(uint8_t type, const Identity& dest, const uint8_t* packet->header = (type << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later int len = 0; + if (type == PAYLOAD_TYPE_TRACE) { + packet->payload[len++] = 0; // reserved: flags:type + } len += dest.copyHashTo(&packet->payload[len]); // dest hash len += self_id.copyHashTo(&packet->payload[len]); // src hash len += Utils::encryptThenMAC(secret, &packet->payload[len], data, data_len); diff --git a/src/Mesh.h b/src/Mesh.h index e5da9406..7e257e3e 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -81,9 +81,19 @@ protected: * \param type one of: PAYLOAD_TYPE_TXT_MSG, PAYLOAD_TYPE_REQ, PAYLOAD_TYPE_RESPONSE * \param sender_idx index of peer, [0..n) where n is what searchPeersByHash() returned * \param secret the pre-calculated shared-secret (handy for sending response packet) + * \param data decrypted data from payload */ virtual void onPeerDataRecv(Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) { } + /** + * \brief A (now verified) TRACE packet has been received (by a known peer). + * NOTE: these can be received multiple times (per sender/msg-id), via different routes + * \param sender_idx index of peer, [0..n) where n is what searchPeersByHash() returned + * \param secret the pre-calculated shared-secret (handy for sending response packet) + * \param data decrypted data from payload (fixed length, one CIPHER_BLOCK) + */ + virtual void onPeerTraceRecv(Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* data) { } + /** * \brief A path TO peer (sender_idx) has been received. (also with optional 'extra' data encoded) * NOTE: these can be received multiple times (per sender), via differen routes diff --git a/src/Packet.cpp b/src/Packet.cpp index a342c37f..82a73339 100644 --- a/src/Packet.cpp +++ b/src/Packet.cpp @@ -10,12 +10,15 @@ Packet::Packet() { payload_len = 0; } - void Packet::calculatePacketHash(uint8_t* hash) const { SHA256 sha; uint8_t t = getPayloadType(); sha.update(&t, 1); - sha.update(payload, payload_len); + if (t == PAYLOAD_TYPE_TRACE) { + sha.update(payload, 3+CIPHER_MAC_SIZE+CIPHER_BLOCK_SIZE); // the 'content' part of TRACE packets is just the fixed-len encrypted part + } else { + sha.update(payload, payload_len); + } sha.finalize(hash, MAX_HASH_SIZE); } diff --git a/src/Packet.h b/src/Packet.h index c8769d8c..c4185875 100644 --- a/src/Packet.h +++ b/src/Packet.h @@ -25,6 +25,7 @@ namespace mesh { #define PAYLOAD_TYPE_GRP_DATA 0x06 // an (unverified) group datagram (prefixed with channel hash, MAC) (enc data: timestamp, blob) #define PAYLOAD_TYPE_ANON_REQ 0x07 // generic request (prefixed with dest_hash, ephemeral pub_key, MAC) (enc data: ...) #define PAYLOAD_TYPE_PATH 0x08 // returned path (prefixed with dest/src hashes, MAC) (enc data: path, extra) +#define PAYLOAD_TYPE_TRACE 0x09 // trace a path, collecting SNI for each hop //... #define PAYLOAD_TYPE_RESERVEDM 0x0F // FUTURE @@ -44,6 +45,7 @@ public: uint16_t payload_len, path_len; uint8_t path[MAX_PATH_SIZE]; uint8_t payload[MAX_PACKET_PAYLOAD]; + float _snr; /** * \brief calculate the hash of payload + type @@ -72,6 +74,8 @@ public: void markDoNotRetransmit() { header = 0xFF; } bool isMarkedDoNotRetransmit() const { return header == 0xFF; } + float getSNR() const { return _snr; } + /** * \brief save entire packet as a blob * \param dest (OUT) destination buffer (assumed to be MAX_MTU_SIZE) diff --git a/src/helpers/BaseChatMesh.cpp b/src/helpers/BaseChatMesh.cpp index 093e0400..9133e795 100644 --- a/src/helpers/BaseChatMesh.cpp +++ b/src/helpers/BaseChatMesh.cpp @@ -135,6 +135,50 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender } } +void BaseChatMesh::onPeerTraceRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* data) { + int i = matching_peer_indexes[sender_idx]; + if (i < 0 || i >= num_contacts) { + MESH_DEBUG_PRINTLN("onPeerTraceRecv: Invalid sender idx: %d", i); + return; + } + + if ((packet->payload[0] & 3) != 0) { + MESH_DEBUG_PRINTLN("onPeerTraceRecv: unknown TRACE sub-type: %u", (uint32_t)packet->payload[0]); + return; + } + + ContactInfo& from = contacts[i]; + + uint32_t timestamp; + memcpy(×tamp, data, 4); // timestamp (by sender's RTC clock - which could be wrong) + uint8_t sender_flags = data[4]; + + int j = 3 + CIPHER_MAC_SIZE + CIPHER_BLOCK_SIZE; // skip fixed-len part + + uint8_t path_hashes[64]; + int8_t path_snr[65]; + uint16_t len; + if (packet->isRouteFlood()) { + memcpy(path_hashes, packet->path, len = packet->path_len); + memset(path_snr, 0, sizeof(path_snr)); + memcpy(path_snr, &packet->payload[j], packet->payload_len - j); // 'track' should just contain SNRs + } else { + len = 0; + while (j + 1 < packet->payload_len) { + path_hashes[len] = packet->payload[j++]; // pairs of Hash + SNR + path_snr[len] = packet->payload[j++]; + len++; + } + } + path_snr[len] = (int8_t)(packet->getSNR()*4); // also include last hop (to this node) + + onContactTraceRecv(from, timestamp, path_hashes, path_snr, len); + + if (sender_flags & 1) { // the 'wants reply' flag + // TODO: send a TRACE packet back + } +} + bool BaseChatMesh::onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) { int i = matching_peer_indexes[sender_idx]; if (i < 0 || i >= num_contacts) { @@ -229,6 +273,25 @@ int BaseChatMesh::sendMessage(const ContactInfo& recipient, uint32_t timestamp, return rc; } +bool BaseChatMesh::sendContactTraceDirect(const ContactInfo& recipient, bool wantReply) { + if (recipient.out_path_len < 0) return false; // Error: no known path + + uint8_t temp[CIPHER_BLOCK_SIZE]; + memset(temp, 0, sizeof(temp)); + + uint32_t timestamp = getRTCClock()->getCurrentTime(); + memcpy(temp, ×tamp, 4); + temp[4] = wantReply ? 1 : 0; + // TODO: any other data to encrypt?? + + auto pkt = createDatagram(PAYLOAD_TYPE_TRACE, recipient.id, recipient.shared_secret, temp, sizeof(temp)); + if (pkt) { + sendDirect(pkt, recipient.out_path, recipient.out_path_len); + return true; // success + } + return false; // error +} + bool BaseChatMesh::sendGroupMessage(uint32_t timestamp, mesh::GroupChannel& channel, const char* sender_name, const char* text, int text_len) { uint8_t temp[5+MAX_TEXT_LEN+32]; memcpy(temp, ×tamp, 4); // mostly an extra blob to help make packet_hash unique diff --git a/src/helpers/BaseChatMesh.h b/src/helpers/BaseChatMesh.h index 814336b5..f77fbd83 100644 --- a/src/helpers/BaseChatMesh.h +++ b/src/helpers/BaseChatMesh.h @@ -87,6 +87,7 @@ protected: virtual void onSendTimeout() = 0; virtual void onChannelMessageRecv(const mesh::GroupChannel& channel, int in_path_len, uint32_t timestamp, const char *text) = 0; virtual void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) = 0; + virtual void onContactTraceRecv(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t hash[], int8_t snr[], uint8_t path_len) = 0; // storage concepts, for sub-classes to override/implement virtual int getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) { return 0; } // not implemented @@ -98,6 +99,7 @@ protected: void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override; void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override; bool onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override; + void onPeerTraceRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* data) override; void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) override; #ifdef MAX_GROUP_CHANNELS int searchChannelsByHash(const uint8_t* hash, mesh::GroupChannel channels[], int max_matches) override; @@ -112,6 +114,7 @@ public: bool shareContactZeroHop(const ContactInfo& contact); uint8_t exportContact(const ContactInfo& contact, uint8_t dest_buf[]); bool importContact(const uint8_t src_buf[], uint8_t len); + bool sendContactTraceDirect(const ContactInfo& recipient, bool wantReply); void resetPathTo(ContactInfo& recipient); void scanRecentContacts(int last_n, ContactVisitor* visitor); ContactInfo* searchContactsByPrefix(const char* name_prefix); From b2fcc692ea5ca0b14552f2afe88024fbe4c02862 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Fri, 7 Mar 2025 12:24:18 +1100 Subject: [PATCH 02/28] * TRACE packet logging fix --- examples/simple_repeater/main.cpp | 2 ++ src/Dispatcher.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index a5f06c1d..c9ccfe9e 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -254,6 +254,8 @@ protected: if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH || pkt->getPayloadType() == PAYLOAD_TYPE_REQ || pkt->getPayloadType() == PAYLOAD_TYPE_RESPONSE || pkt->getPayloadType() == PAYLOAD_TYPE_TXT_MSG) { f.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[1], (uint32_t)pkt->payload[0]); + } else if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) { + f.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[2], (uint32_t)pkt->payload[1]); } else { f.printf("\n"); } diff --git a/src/Dispatcher.cpp b/src/Dispatcher.cpp index 4739099f..bba19ec2 100644 --- a/src/Dispatcher.cpp +++ b/src/Dispatcher.cpp @@ -125,6 +125,8 @@ void Dispatcher::checkRecv() { if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH || pkt->getPayloadType() == PAYLOAD_TYPE_REQ || pkt->getPayloadType() == PAYLOAD_TYPE_RESPONSE || pkt->getPayloadType() == PAYLOAD_TYPE_TXT_MSG) { Serial.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[1], (uint32_t)pkt->payload[0]); + } else if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) { + Serial.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[2], (uint32_t)pkt->payload[1]); } else { Serial.printf("\n"); } From 544adec2b6cdae174d817409893ce2429ae36f08 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Fri, 7 Mar 2025 12:32:23 +1100 Subject: [PATCH 03/28] * refactor Packet::_snr to single byte --- src/Dispatcher.cpp | 2 +- src/Packet.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Dispatcher.cpp b/src/Dispatcher.cpp index bba19ec2..b67ba7cf 100644 --- a/src/Dispatcher.cpp +++ b/src/Dispatcher.cpp @@ -108,7 +108,7 @@ void Dispatcher::checkRecv() { pkt->payload_len = len - i; // payload is remainder memcpy(pkt->payload, &raw[i], pkt->payload_len); - score = _radio->packetScore(pkt->_snr = _radio->getLastSNR(), len); + score = _radio->packetScore(pkt->_snr = (_radio->getLastSNR() * 4.0f), len); air_time = _radio->getEstAirtimeFor(len); } } diff --git a/src/Packet.h b/src/Packet.h index 83520fe7..e20b3a49 100644 --- a/src/Packet.h +++ b/src/Packet.h @@ -45,7 +45,7 @@ public: uint16_t payload_len, path_len; uint8_t path[MAX_PATH_SIZE]; uint8_t payload[MAX_PACKET_PAYLOAD]; - float _snr; + int8_t _snr; /** * \brief calculate the hash of payload + type @@ -74,7 +74,7 @@ public: void markDoNotRetransmit() { header = 0xFF; } bool isMarkedDoNotRetransmit() const { return header == 0xFF; } - float getSNR() const { return _snr; } + float getSNR() const { return ((float)_snr) / 4.0f; } /** * \brief save entire packet as a blob From e534e1b529792e69da9638897d05dfcf92df6f92 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Fri, 7 Mar 2025 14:17:37 +1100 Subject: [PATCH 04/28] * companion: FIRMWARE_VER_CODE now bumped to 3. * companion: new RESP_CODE_CONTACT_MSG_RECV_V3, and _CHANNEL_MSG_RECV_V3. (now with packet SNR included) --- examples/companion_radio/main.cpp | 49 +++++++++++++++++++--------- examples/simple_secure_chat/main.cpp | 14 ++++---- src/helpers/BaseChatMesh.cpp | 8 ++--- src/helpers/BaseChatMesh.h | 8 ++--- 4 files changed, 48 insertions(+), 31 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 8a8e1528..c45b17e0 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -117,7 +117,7 @@ static uint32_t _atoi(const char* sp) { /*------------ Frame Protocol --------------*/ -#define FIRMWARE_VER_CODE 2 +#define FIRMWARE_VER_CODE 3 #ifndef FIRMWARE_BUILD_DATE #define FIRMWARE_BUILD_DATE "3 Mar 2025" @@ -165,8 +165,8 @@ static uint32_t _atoi(const char* sp) { #define RESP_CODE_END_OF_CONTACTS 4 // last reply to CMD_GET_CONTACTS #define RESP_CODE_SELF_INFO 5 // reply to CMD_APP_START #define RESP_CODE_SENT 6 // reply to CMD_SEND_TXT_MSG -#define RESP_CODE_CONTACT_MSG_RECV 7 // a reply to CMD_SYNC_NEXT_MESSAGE -#define RESP_CODE_CHANNEL_MSG_RECV 8 // a reply to CMD_SYNC_NEXT_MESSAGE +#define RESP_CODE_CONTACT_MSG_RECV 7 // a reply to CMD_SYNC_NEXT_MESSAGE (ver < 3) +#define RESP_CODE_CHANNEL_MSG_RECV 8 // a reply to CMD_SYNC_NEXT_MESSAGE (ver < 3) #define RESP_CODE_CURR_TIME 9 // a reply to CMD_GET_DEVICE_TIME #define RESP_CODE_NO_MORE_MESSAGES 10 // a reply to CMD_SYNC_NEXT_MESSAGE #define RESP_CODE_EXPORT_CONTACT 11 @@ -174,6 +174,8 @@ static uint32_t _atoi(const char* sp) { #define RESP_CODE_DEVICE_INFO 13 // a reply to CMD_DEVICE_QEURY #define RESP_CODE_PRIVATE_KEY 14 // a reply to CMD_EXPORT_PRIVATE_KEY #define RESP_CODE_DISABLED 15 +#define RESP_CODE_CONTACT_MSG_RECV_V3 16 // a reply to CMD_SYNC_NEXT_MESSAGE (ver >= 3) +#define RESP_CODE_CHANNEL_MSG_RECV_V3 17 // a reply to CMD_SYNC_NEXT_MESSAGE (ver >= 3) // these are _pushed_ to client app at any time #define PUSH_CODE_ADVERT 0x80 @@ -471,11 +473,18 @@ protected: return checkConnectionsAck(data); } - void queueMessage(const ContactInfo& from, uint8_t txt_type, uint8_t path_len, uint32_t sender_timestamp, const uint8_t* extra, int extra_len, const char *text) { + void queueMessage(const ContactInfo& from, uint8_t txt_type, mesh::Packet* pkt, uint32_t sender_timestamp, const uint8_t* extra, int extra_len, const char *text) { int i = 0; - out_frame[i++] = RESP_CODE_CONTACT_MSG_RECV; + if (app_target_ver >= 3) { + out_frame[i++] = RESP_CODE_CONTACT_MSG_RECV_V3; + out_frame[i++] = (int8_t)(pkt->getSNR() * 4); + out_frame[i++] = 0; // reserved1 + out_frame[i++] = 0; // reserved2 + } else { + out_frame[i++] = RESP_CODE_CONTACT_MSG_RECV; + } memcpy(&out_frame[i], from.id.pub_key, 6); i += 6; // just 6-byte prefix - out_frame[i++] = path_len; + uint8_t path_len = out_frame[i++] = pkt->isRouteFlood() ? pkt->path_len : 0xFF; out_frame[i++] = txt_type; memcpy(&out_frame[i], &sender_timestamp, 4); i += 4; if (extra_len > 0) { @@ -500,27 +509,35 @@ protected: #endif } - void onMessageRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const char *text) override { + void onMessageRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) override { markConnectionActive(from); // in case this is from a server, and we have a connection - queueMessage(from, TXT_TYPE_PLAIN, path_len, sender_timestamp, NULL, 0, text); + queueMessage(from, TXT_TYPE_PLAIN, pkt, sender_timestamp, NULL, 0, text); } - void onCommandDataRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const char *text) override { + void onCommandDataRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) override { markConnectionActive(from); // in case this is from a server, and we have a connection - queueMessage(from, TXT_TYPE_CLI_DATA, path_len, sender_timestamp, NULL, 0, text); + queueMessage(from, TXT_TYPE_CLI_DATA, pkt, sender_timestamp, NULL, 0, text); } - void onSignedMessageRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) override { + void onSignedMessageRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) override { markConnectionActive(from); saveContacts(); // from.sync_since change needs to be persisted - queueMessage(from, TXT_TYPE_SIGNED_PLAIN, path_len, sender_timestamp, sender_prefix, 4, text); + queueMessage(from, TXT_TYPE_SIGNED_PLAIN, pkt, sender_timestamp, sender_prefix, 4, text); } - void onChannelMessageRecv(const mesh::GroupChannel& channel, int in_path_len, uint32_t timestamp, const char *text) override { + void onChannelMessageRecv(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t timestamp, const char *text) override { int i = 0; - out_frame[i++] = RESP_CODE_CHANNEL_MSG_RECV; + if (app_target_ver >= 3) { + out_frame[i++] = RESP_CODE_CHANNEL_MSG_RECV_V3; + out_frame[i++] = (int8_t)(pkt->getSNR() * 4); + out_frame[i++] = 0; // reserved1 + out_frame[i++] = 0; // reserved2 + } else { + out_frame[i++] = RESP_CODE_CHANNEL_MSG_RECV; + } + out_frame[i++] = 0; // FUTURE: channel_idx (will just be 'public' for now) - out_frame[i++] = in_path_len < 0 ? 0xFF : in_path_len; + uint8_t path_len = out_frame[i++] = pkt->isRouteFlood() ? pkt->path_len : 0xFF; out_frame[i++] = TXT_TYPE_PLAIN; memcpy(&out_frame[i], ×tamp, 4); i += 4; int tlen = strlen(text); // TODO: UTF-8 ?? @@ -538,7 +555,7 @@ protected: soundBuzzer(); } #ifdef DISPLAY_CLASS - ui_task.showMsgPreview(in_path_len < 0 ? 0xFF : in_path_len, "Public", text); + ui_task.showMsgPreview(path_len, "Public", text); #endif } diff --git a/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index 2051d4a0..b03c479f 100644 --- a/examples/simple_secure_chat/main.cpp +++ b/examples/simple_secure_chat/main.cpp @@ -254,8 +254,8 @@ protected: return false; } - void onMessageRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const char *text) override { - Serial.printf("(%s) MSG -> from %s\n", path_len == 0xFF ? "DIRECT" : "FLOOD", from.name); + void onMessageRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) override { + Serial.printf("(%s) MSG -> from %s\n", pkt->isRouteDirect() ? "DIRECT" : "FLOOD", from.name); Serial.printf(" %s\n", text); if (strcmp(text, "clock sync") == 0) { // special text command @@ -263,16 +263,16 @@ protected: } } - void onCommandDataRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const char *text) override { + void onCommandDataRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) override { } - void onSignedMessageRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) override { + void onSignedMessageRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) override { } - void onChannelMessageRecv(const mesh::GroupChannel& channel, int in_path_len, uint32_t timestamp, const char *text) override { - if (in_path_len < 0) { + void onChannelMessageRecv(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t timestamp, const char *text) override { + if (pkt->isRouteDirect()) { Serial.printf("PUBLIC CHANNEL MSG -> (Direct!)\n"); } else { - Serial.printf("PUBLIC CHANNEL MSG -> (Flood) hops %d\n", in_path_len); + Serial.printf("PUBLIC CHANNEL MSG -> (Flood) hops %d\n", pkt->path_len); } Serial.printf(" %s\n", text); } diff --git a/src/helpers/BaseChatMesh.cpp b/src/helpers/BaseChatMesh.cpp index db937787..4ae0b1b1 100644 --- a/src/helpers/BaseChatMesh.cpp +++ b/src/helpers/BaseChatMesh.cpp @@ -105,7 +105,7 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender data[len] = 0; // need to make a C string again, with null terminator if (flags == TXT_TYPE_PLAIN) { - onMessageRecv(from, packet->isRouteFlood() ? packet->path_len : 0xFF, timestamp, (const char *) &data[5]); // let UI know + onMessageRecv(from, packet, timestamp, (const char *) &data[5]); // let UI know uint32_t ack_hash; // calc truncated hash of the message timestamp + text + sender pub_key, to prove to sender that we got it mesh::Utils::sha256((uint8_t *) &ack_hash, 4, data, 5 + strlen((char *)&data[5]), from.id.pub_key, PUB_KEY_SIZE); @@ -126,7 +126,7 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender } } } else if (flags == TXT_TYPE_CLI_DATA) { - onCommandDataRecv(from, packet->isRouteFlood() ? packet->path_len : 0xFF, timestamp, (const char *) &data[5]); // let UI know + onCommandDataRecv(from, packet, timestamp, (const char *) &data[5]); // let UI know // NOTE: no ack expected for CLI_DATA replies if (packet->isRouteFlood()) { @@ -138,7 +138,7 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender if (timestamp > from.sync_since) { // make sure 'sync_since' is up-to-date from.sync_since = timestamp; } - onSignedMessageRecv(from, packet->isRouteFlood() ? packet->path_len : 0xFF, timestamp, &data[5], (const char *) &data[9]); // let UI know + onSignedMessageRecv(from, packet, timestamp, &data[5], (const char *) &data[9]); // let UI know uint32_t ack_hash; // calc truncated hash of the message timestamp + text + OUR pub_key, to prove to sender that we got it mesh::Utils::sha256((uint8_t *) &ack_hash, 4, data, 9 + strlen((char *)&data[9]), self_id.pub_key, PUB_KEY_SIZE); @@ -266,7 +266,7 @@ void BaseChatMesh::onGroupDataRecv(mesh::Packet* packet, uint8_t type, const mes data[len] = 0; // need to make a C string again, with null terminator // notify UI of this new message - onChannelMessageRecv(channel, packet->isRouteFlood() ? packet->path_len : -1, timestamp, (const char *) &data[5]); // let UI know + onChannelMessageRecv(channel, packet, timestamp, (const char *) &data[5]); // let UI know } } diff --git a/src/helpers/BaseChatMesh.h b/src/helpers/BaseChatMesh.h index d2b38c7a..8d22cbea 100644 --- a/src/helpers/BaseChatMesh.h +++ b/src/helpers/BaseChatMesh.h @@ -100,13 +100,13 @@ protected: virtual void onDiscoveredContact(ContactInfo& contact, bool is_new) = 0; virtual bool processAck(const uint8_t *data) = 0; virtual void onContactPathUpdated(const ContactInfo& contact) = 0; - virtual void onMessageRecv(const ContactInfo& contact, uint8_t path_len, uint32_t sender_timestamp, const char *text) = 0; - virtual void onCommandDataRecv(const ContactInfo& contact, uint8_t path_len, uint32_t sender_timestamp, const char *text) = 0; - virtual void onSignedMessageRecv(const ContactInfo& contact, uint8_t path_len, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) = 0; + virtual void onMessageRecv(const ContactInfo& contact, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) = 0; + virtual void onCommandDataRecv(const ContactInfo& contact, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) = 0; + virtual void onSignedMessageRecv(const ContactInfo& contact, mesh::Packet* pkt, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) = 0; virtual uint32_t calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const = 0; virtual uint32_t calcDirectTimeoutMillisFor(uint32_t pkt_airtime_millis, uint8_t path_len) const = 0; virtual void onSendTimeout() = 0; - virtual void onChannelMessageRecv(const mesh::GroupChannel& channel, int in_path_len, uint32_t timestamp, const char *text) = 0; + virtual void onChannelMessageRecv(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t timestamp, const char *text) = 0; virtual void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) = 0; virtual void onContactTraceRecv(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t hash[], int8_t snr[], uint8_t path_len) = 0; From 790898dbc51063cd5354ac1776e976f0e9a15bb6 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Fri, 7 Mar 2025 15:09:29 +1100 Subject: [PATCH 05/28] * companion: better incoming ACK processing (match prev attempts) --- examples/companion_radio/main.cpp | 46 ++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index c45b17e0..ff2cd134 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -210,12 +210,10 @@ class MyMesh : public BaseChatMesh { RADIO_CLASS* _phy; IdentityStore* _identity_store; NodePrefs _prefs; - uint32_t expected_ack_crc; // TODO: keep table of expected ACKs uint32_t pending_login; uint32_t pending_status; mesh::GroupChannel* _public; BaseSerialInterface* _serial; - unsigned long last_msg_sent; ContactsIterator _iter; uint32_t _iter_filter_since; uint32_t _most_recent_lastmod; @@ -232,6 +230,14 @@ class MyMesh : public BaseChatMesh { int offline_queue_len; Frame offline_queue[OFFLINE_QUEUE_SIZE]; + struct AckTableEntry { + unsigned long msg_sent; + uint32_t ack; + }; + #define EXPECTED_ACK_TABLE_SIZE 8 + AckTableEntry expected_ack_table[EXPECTED_ACK_TABLE_SIZE]; // circular table + int next_ack_idx; + void loadMainIdentity(mesh::RNG& trng) { if (!_identity_store->load("_main", self_id)) { self_id = mesh::LocalIdentity(&trng); // create new random identity @@ -458,17 +464,19 @@ protected: } bool processAck(const uint8_t *data) override { - // TODO: see if matches any in a table - if (memcmp(data, &expected_ack_crc, 4) == 0) { // got an ACK from recipient - out_frame[0] = PUSH_CODE_SEND_CONFIRMED; - memcpy(&out_frame[1], data, 4); - uint32_t trip_time = _ms->getMillis() - last_msg_sent; - memcpy(&out_frame[5], &trip_time, 4); - _serial->writeFrame(out_frame, 9); + // see if matches any in a table + for (int i = 0; i < EXPECTED_ACK_TABLE_SIZE; i++) { + if (memcmp(data, &expected_ack_table[i].ack, 4) == 0) { // got an ACK from recipient + out_frame[0] = PUSH_CODE_SEND_CONFIRMED; + memcpy(&out_frame[1], data, 4); + uint32_t trip_time = _ms->getMillis() - expected_ack_table[i].msg_sent; + memcpy(&out_frame[5], &trip_time, 4); + _serial->writeFrame(out_frame, 9); - // NOTE: the same ACK can be received multiple times! - expected_ack_crc = 0; // reset our expected hash, now that we have received ACK - return true; + // NOTE: the same ACK can be received multiple times! + expected_ack_table[i].ack = 0; // clear expected hash, now that we have received ACK + return true; + } } return checkConnectionsAck(data); } @@ -637,6 +645,7 @@ public: app_target_ver = 0; _identity_store = NULL; pending_login = pending_status = 0; + next_ack_idx = 0; // defaults memset(&_prefs, 0, sizeof(_prefs)); @@ -824,21 +833,26 @@ public: uint32_t est_timeout; text[tlen] = 0; // ensure null int result; + uint32_t expected_ack; if (txt_type == TXT_TYPE_CLI_DATA) { result = sendCommandData(*recipient, msg_timestamp, attempt, text, est_timeout); - expected_ack_crc = 0; // no Ack expected + expected_ack = 0; // no Ack expected } else { - result = sendMessage(*recipient, msg_timestamp, attempt, text, expected_ack_crc, est_timeout); + result = sendMessage(*recipient, msg_timestamp, attempt, text, expected_ack, est_timeout); } // TODO: add expected ACK to table if (result == MSG_SEND_FAILED) { writeErrFrame(); } else { - last_msg_sent = _ms->getMillis(); + if (expected_ack) { + expected_ack_table[next_ack_idx].msg_sent = _ms->getMillis(); // add to circular table + expected_ack_table[next_ack_idx].ack = expected_ack; + next_ack_idx = (next_ack_idx + 1) % EXPECTED_ACK_TABLE_SIZE; + } out_frame[0] = RESP_CODE_SENT; out_frame[1] = (result == MSG_SEND_SENT_FLOOD) ? 1 : 0; - memcpy(&out_frame[2], &expected_ack_crc, 4); + memcpy(&out_frame[2], &expected_ack, 4); memcpy(&out_frame[6], &est_timeout, 4); _serial->writeFrame(out_frame, 10); } From 2edbd92b3bb9991af67f3652780830c707175bb9 Mon Sep 17 00:00:00 2001 From: James Hall Date: Thu, 13 Mar 2025 14:07:54 -0400 Subject: [PATCH 06/28] Added Support for the LilyGo TBeam v1.2 SX1276 --- .vscode/settings.json | 3 + examples/companion_radio/main.cpp | 7 ++ platformio.ini | 38 +++++++++++ src/helpers/TBeamBoard.h | 104 ++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 .vscode/settings.json create mode 100644 src/helpers/TBeamBoard.h diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..06b08423 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "C_Cpp.dimInactiveRegions": false +} \ No newline at end of file diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index f3374ecb..ebde045e 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -96,6 +96,10 @@ #include #include static TechoBoard board; +#elif defined(LILYGO_TBEAM) + #include + #include + static TBeamBoard board; #else #error "need to provide a 'board' object" #endif @@ -1319,6 +1323,9 @@ RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BU #elif defined(LILYGO_TLORA) SPIClass spi; RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi); +#elif defined(LILYGO_TBEAM) +SPIClass spi; +RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi); #elif defined(P_LORA_SCLK) SPIClass spi; RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); diff --git a/platformio.ini b/platformio.ini index 47aca405..af7cef4c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -654,6 +654,44 @@ build_flags = ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 +[LilyGo_TBeam] +extends = esp32_base +board = ttgo-t-beam +build_flags = + ${esp32_base.build_flags} + -D LILYGO_TBEAM + -D RADIO_CLASS=CustomSX1276 + -D WRAPPER_CLASS=CustomSX1276Wrapper + -D LORA_TX_POWER=20 + -D P_LORA_TX_LED=4 +build_src_filter = ${esp32_base.build_src_filter} +board_build.partitions = min_spiffs.csv ; get around 4mb flash limit + +[env:Tbeam_companion_radio_ble] +extends = LilyGo_TBeam +board_build.upload.maximum_ram_size=2000000 +build_flags = + ${LilyGo_TBeam.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=1 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 + -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 + -D RADIOLIB_DEBUG_BASIC=1 +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_TBeam.build_src_filter} + + + +<../examples/companion_radio/main.cpp> +lib_deps = + ${LilyGo_TBeam.lib_deps} + densaugeo/base64 @ ~1.4.0 + lewisxhe/XPowersLib@^0.2.7 + + ; ----------------- NRF52 --------------------- [nrf52_base] extends = arduino_base diff --git a/src/helpers/TBeamBoard.h b/src/helpers/TBeamBoard.h new file mode 100644 index 00000000..60e5f4fa --- /dev/null +++ b/src/helpers/TBeamBoard.h @@ -0,0 +1,104 @@ +#pragma once + +// Defined using AXP2102 +#define XPOWERS_CHIP_AXP2101 + +#include +#include +#include "XPowersLib.h" + +#ifndef CONFIG_PMU_SDA +#define CONFIG_PMU_SDA 21 +#endif + +#ifndef CONFIG_PMU_SCL +#define CONFIG_PMU_SCL 22 +#endif + +#ifndef CONFIG_PMU_IRQ +#define CONFIG_PMU_IRQ 35 +#endif + +bool pmu_flag = 0; +XPowersPMU power; + +const uint8_t i2c_sda = CONFIG_PMU_SDA; +const uint8_t i2c_scl = CONFIG_PMU_SCL; +const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ; + +void setFlag(void) +{ + pmu_flag = true; +} + + + +// LoRa radio module pins for TBeam +#define P_LORA_DIO_0 26 +#define P_LORA_DIO_2 32 +#define P_LORA_DIO_1 33 +#define P_LORA_NSS 18 +#define P_LORA_RESET 14 +#define P_LORA_BUSY RADIOLIB_NC +#define P_LORA_SCLK 5 +#define P_LORA_MISO 19 +#define P_LORA_MOSI 27 + +// built-ins +//#define PIN_VBAT_READ 37 +//#define PIN_LED_BUILTIN 25 + +#include "ESP32Board.h" + +#include + +class TBeamBoard : public ESP32Board { +public: + void begin() { + ESP32Board::begin(); + power.setALDO2Voltage(3300); + power.enableALDO2(); + + esp_reset_reason_t reason = esp_reset_reason(); + if (reason == ESP_RST_DEEPSLEEP) { + long wakeup_source = esp_sleep_get_ext1_wakeup_status(); + if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep) + startup_reason = BD_STARTUP_RX_PACKET; + } + + rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS); + rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_1); + } + } + + void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1) { + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); + + // Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep + rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY); + rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1); + + rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS); + + if (pin_wake_btn < 0) { + esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet + } else { + esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet OR wake btn + } + + if (secs > 0) { + esp_sleep_enable_timer_wakeup(secs * 1000000); + } + + // Finally set ESP32 into sleep + esp_deep_sleep_start(); // CPU halts here and never returns! + } + + uint16_t getBattMilliVolts() override { + return 0; + } + + const char* getManufacturerName() const override { + return "LilyGo T-Beam"; + } +}; From aca3486f88f3e35ac4e4a359fca738b27ffcdc3f Mon Sep 17 00:00:00 2001 From: James Hall Date: Thu, 13 Mar 2025 20:35:44 -0400 Subject: [PATCH 07/28] Update settings.json --- .vscode/settings.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 06b08423..8b137891 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1 @@ -{ - "C_Cpp.dimInactiveRegions": false -} \ No newline at end of file + From 6d8aa5817b0782b92b22ab4d249904ceae335561 Mon Sep 17 00:00:00 2001 From: James Hall Date: Thu, 13 Mar 2025 20:41:32 -0400 Subject: [PATCH 08/28] removed pmu flag --- src/helpers/TBeamBoard.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/helpers/TBeamBoard.h b/src/helpers/TBeamBoard.h index 60e5f4fa..9587e96c 100644 --- a/src/helpers/TBeamBoard.h +++ b/src/helpers/TBeamBoard.h @@ -19,19 +19,13 @@ #define CONFIG_PMU_IRQ 35 #endif -bool pmu_flag = 0; + XPowersPMU power; const uint8_t i2c_sda = CONFIG_PMU_SDA; const uint8_t i2c_scl = CONFIG_PMU_SCL; const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ; -void setFlag(void) -{ - pmu_flag = true; -} - - // LoRa radio module pins for TBeam #define P_LORA_DIO_0 26 From b41d1a56f606f424b67e6a3948fb965eef19dc5d Mon Sep 17 00:00:00 2001 From: James Hall Date: Thu, 13 Mar 2025 20:42:36 -0400 Subject: [PATCH 09/28] Delete .vscode/settings.json --- .vscode/settings.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 8b137891..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1 +0,0 @@ - From aca0bcc91970f85c3030dcad766f4d4c15886850 Mon Sep 17 00:00:00 2001 From: James Hall Date: Fri, 14 Mar 2025 14:22:13 -0400 Subject: [PATCH 10/28] removed unnecessary constants --- src/helpers/TBeamBoard.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/helpers/TBeamBoard.h b/src/helpers/TBeamBoard.h index 9587e96c..5c8bc224 100644 --- a/src/helpers/TBeamBoard.h +++ b/src/helpers/TBeamBoard.h @@ -22,11 +22,6 @@ XPowersPMU power; -const uint8_t i2c_sda = CONFIG_PMU_SDA; -const uint8_t i2c_scl = CONFIG_PMU_SCL; -const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ; - - // LoRa radio module pins for TBeam #define P_LORA_DIO_0 26 #define P_LORA_DIO_2 32 From c2f92534df4ffc196c5772af6d7243da90593abc Mon Sep 17 00:00:00 2001 From: James Hall Date: Fri, 14 Mar 2025 14:27:10 -0400 Subject: [PATCH 11/28] removed unnecessary defines --- src/helpers/TBeamBoard.h | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/helpers/TBeamBoard.h b/src/helpers/TBeamBoard.h index 5c8bc224..9c9f5820 100644 --- a/src/helpers/TBeamBoard.h +++ b/src/helpers/TBeamBoard.h @@ -7,19 +7,6 @@ #include #include "XPowersLib.h" -#ifndef CONFIG_PMU_SDA -#define CONFIG_PMU_SDA 21 -#endif - -#ifndef CONFIG_PMU_SCL -#define CONFIG_PMU_SCL 22 -#endif - -#ifndef CONFIG_PMU_IRQ -#define CONFIG_PMU_IRQ 35 -#endif - - XPowersPMU power; // LoRa radio module pins for TBeam @@ -45,6 +32,7 @@ class TBeamBoard : public ESP32Board { public: void begin() { ESP32Board::begin(); + power.setALDO2Voltage(3300); power.enableALDO2(); From bc6e4930d9a9df9157149afe06f16ead59f001d0 Mon Sep 17 00:00:00 2001 From: James Hall Date: Fri, 14 Mar 2025 19:54:46 -0400 Subject: [PATCH 12/28] Cleaned up code --- src/helpers/TBeamBoard.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/helpers/TBeamBoard.h b/src/helpers/TBeamBoard.h index 9c9f5820..0114dbdc 100644 --- a/src/helpers/TBeamBoard.h +++ b/src/helpers/TBeamBoard.h @@ -1,12 +1,12 @@ #pragma once -// Defined using AXP2102 -#define XPOWERS_CHIP_AXP2101 #include #include #include "XPowersLib.h" +// Defined using AXP2102 +#define XPOWERS_CHIP_AXP2101 XPowersPMU power; // LoRa radio module pins for TBeam From aeda21840204f80c12e722f7e4c6dcc599a3c8de Mon Sep 17 00:00:00 2001 From: James Hall Date: Sat, 15 Mar 2025 13:09:15 -0400 Subject: [PATCH 13/28] Update TBeamBoard.h --- src/helpers/TBeamBoard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/TBeamBoard.h b/src/helpers/TBeamBoard.h index 0114dbdc..a6cff678 100644 --- a/src/helpers/TBeamBoard.h +++ b/src/helpers/TBeamBoard.h @@ -7,7 +7,7 @@ // Defined using AXP2102 #define XPOWERS_CHIP_AXP2101 -XPowersPMU power; +XPowersAXP2101 power; // LoRa radio module pins for TBeam #define P_LORA_DIO_0 26 From 0eed29b99ef3b636ba4501c4bd63d526f3903c0f Mon Sep 17 00:00:00 2001 From: lincomatic Date: Sun, 16 Mar 2025 16:49:55 -0700 Subject: [PATCH 14/28] fix compilation error --- src/helpers/CustomLLCC68.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/CustomLLCC68.h b/src/helpers/CustomLLCC68.h index 9d829934..49a49ca7 100644 --- a/src/helpers/CustomLLCC68.h +++ b/src/helpers/CustomLLCC68.h @@ -9,7 +9,7 @@ class CustomLLCC68 : public LLCC68 { CustomLLCC68(Module *mod) : LLCC68(mod) { } bool isReceiving() { - uint16_t irq = getIrqStatus(); + uint16_t irq = getIrqFlags(); bool hasPreamble = (irq & SX126X_IRQ_HEADER_VALID); return hasPreamble; } From bdeec374efa675eb83a8836f2a91b72e1b51948b Mon Sep 17 00:00:00 2001 From: lincomatic Date: Sun, 16 Mar 2025 17:48:52 -0700 Subject: [PATCH 15/28] add ProMicroLLCC68 for Faketec w/ LLCC68 --- examples/companion_radio/main.cpp | 1 + examples/simple_repeater/main.cpp | 1 + examples/simple_room_server/main.cpp | 1 + examples/simple_secure_chat/main.cpp | 1 + platformio.ini | 85 ++++++++++++++++++++++++++++ 5 files changed, 89 insertions(+) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 3733470a..b218db11 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -99,6 +99,7 @@ #elif defined(FAKETEC) #include #include + #include static faketecBoard board; #else #error "need to provide a 'board' object" diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 1bb42bda..c5793829 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -99,6 +99,7 @@ #elif defined(FAKETEC) #include #include + #include static faketecBoard board; #else #error "need to provide a 'board' object" diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index eb69bf50..87b75629 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -103,6 +103,7 @@ #elif defined(FAKETEC) #include #include + #include static faketecBoard board; #else #error "need to provide a 'board' object" diff --git a/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index 248353aa..41c55e17 100644 --- a/examples/simple_secure_chat/main.cpp +++ b/examples/simple_secure_chat/main.cpp @@ -81,6 +81,7 @@ #elif defined(FAKETEC) #include #include + #include static faketecBoard board; #else #error "need to provide a 'board' object" diff --git a/platformio.ini b/platformio.ini index fe008c58..69f0fe03 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1082,4 +1082,89 @@ build_src_filter = ${faketec.build_src_filter} + +build_flags = ${nrf52840_base.build_flags} + -D FAKETEC + -D RADIO_CLASS=CustomLLCC68 + -D WRAPPER_CLASS=CustomLLCC68Wrapper + -D LORA_TX_POWER=22 + -D SX126X_CURRENT_LIMIT=130 + -D SX126X_RX_BOOSTED_GAIN=1 + +[env:ProMicroLLCC68_Repeater] +extends = ProMicroLLCC68 +build_src_filter = ${ProMicroLLCC68.build_src_filter} +<../examples/simple_repeater/main.cpp> +build_flags = + ${ProMicroLLCC68.build_flags} + -D ADVERT_NAME="\"ProMicroLLCC68 Repeater\"" + -D ADMIN_PASSWORD="\"password\"" +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${ProMicroLLCC68.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:ProMicroLLCC68_room_server] +extends = ProMicroLLCC68 +build_src_filter = ${ProMicroLLCC68.build_src_filter} +<../examples/simple_room_server/main.cpp> +build_flags = + ${ProMicroLLCC68.build_flags} + -D ADVERT_NAME="\"ProMicroLLCC68 Room\"" + -D ADMIN_PASSWORD="\"password\"" + -D ROOM_PASSWORD="\"hello\"" +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${ProMicroLLCC68.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:ProMicroLLCC68_terminal_chat] +extends = ProMicroLLCC68 +build_flags = + ${ProMicroLLCC68.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${ProMicroLLCC68.build_src_filter} +<../examples/simple_secure_chat/main.cpp> +lib_deps = + ${ProMicroLLCC68.lib_deps} + densaugeo/base64 @ ~1.4.0 + adafruit/RTClib @ ^2.1.3 + +[env:ProMicroLLCC68_companion_radio_usb] +extends = ProMicroLLCC68 +build_flags = + ${ProMicroLLCC68.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 +; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 +; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 +build_src_filter = ${ProMicroLLCC68.build_src_filter} +<../examples/companion_radio/main.cpp> +lib_deps = + ${ProMicroLLCC68.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0 + +[env:ProMicroLLCC68_companion_radio_ble] +extends = ProMicroLLCC68 +build_flags = + ${ProMicroLLCC68.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 + -D ENABLE_PRIVATE_KEY_EXPORT=1 + -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${ProMicroLLCC68.build_src_filter} + +<../examples/companion_radio/main.cpp> +lib_deps = + ${ProMicroLLCC68.lib_deps} + adafruit/RTClib @ ^2.1.3 densaugeo/base64 @ ~1.4.0 \ No newline at end of file From fe4fdeb2362dd2ce6a815692c61794f178c0ef56 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Mon, 17 Mar 2025 17:56:12 +1100 Subject: [PATCH 16/28] * redesigned TRACE packet structure --- examples/companion_radio/main.cpp | 4 -- examples/simple_repeater/main.cpp | 2 - examples/simple_secure_chat/main.cpp | 4 -- src/Dispatcher.cpp | 2 - src/Mesh.cpp | 99 +++++++++++++++++----------- src/Mesh.h | 17 +++-- src/Packet.cpp | 6 +- src/helpers/BaseChatMesh.cpp | 63 ------------------ src/helpers/BaseChatMesh.h | 3 - 9 files changed, 71 insertions(+), 129 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index e2fcc202..d06b4f12 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -710,10 +710,6 @@ protected: } } - void onContactTraceRecv(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t hash[], int8_t snr[], uint8_t path_len) override { - // TODO: write an out_frame - } - uint32_t calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const override { return SEND_TIMEOUT_BASE_MILLIS + (FLOOD_SEND_TIMEOUT_FACTOR * pkt_airtime_millis); } diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 04072f84..1bb42bda 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -273,8 +273,6 @@ protected: if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH || pkt->getPayloadType() == PAYLOAD_TYPE_REQ || pkt->getPayloadType() == PAYLOAD_TYPE_RESPONSE || pkt->getPayloadType() == PAYLOAD_TYPE_TXT_MSG) { f.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[1], (uint32_t)pkt->payload[0]); - } else if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) { - f.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[2], (uint32_t)pkt->payload[1]); } else { f.printf("\n"); } diff --git a/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index ce166d78..94273a68 100644 --- a/examples/simple_secure_chat/main.cpp +++ b/examples/simple_secure_chat/main.cpp @@ -285,10 +285,6 @@ protected: // not supported } - void onContactTraceRecv(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t hash[], int8_t snr[], uint8_t path_len) override { - // TODO: write an out_frame - } - uint32_t calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const override { return SEND_TIMEOUT_BASE_MILLIS + (FLOOD_SEND_TIMEOUT_FACTOR * pkt_airtime_millis); } diff --git a/src/Dispatcher.cpp b/src/Dispatcher.cpp index 7588bcf2..65f9687f 100644 --- a/src/Dispatcher.cpp +++ b/src/Dispatcher.cpp @@ -140,8 +140,6 @@ void Dispatcher::checkRecv() { if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH || pkt->getPayloadType() == PAYLOAD_TYPE_REQ || pkt->getPayloadType() == PAYLOAD_TYPE_RESPONSE || pkt->getPayloadType() == PAYLOAD_TYPE_TXT_MSG) { Serial.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[1], (uint32_t)pkt->payload[0]); - } else if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) { - Serial.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[2], (uint32_t)pkt->payload[1]); } else { Serial.printf("\n"); } diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 02f209c2..0a0fd769 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -41,6 +41,30 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { return ACTION_RELEASE; } + if (pkt->isRouteDirect() && pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) { + if (pkt->path_len < MAX_PATH_SIZE) { + uint8_t i = 0; + uint32_t trace_tag; + memcpy(&trace_tag, &pkt->payload[i], 4); i += 4; + uint32_t auth_code; + memcpy(&auth_code, &pkt->payload[i], 4); i += 4; + uint8_t flags = pkt->payload[i++]; + + uint8_t len = pkt->payload_len - i; + if (pkt->path_len >= len) { // TRACE has reached end of given path + onTraceRecv(pkt, trace_tag, auth_code, flags, pkt->path, &pkt->payload[i], len); + } else if (self_id.isHashMatch(&pkt->payload[i + pkt->path_len]) && allowPacketForward(pkt) && !_tables->hasSeen(pkt)) { + // append SNR (Not hash!) + pkt->path[pkt->path_len] = (int8_t) (pkt->getSNR()*4); + pkt->path_len += PATH_HASH_SIZE; + + uint32_t d = getDirectRetransmitDelay(pkt); + return ACTION_RETRANSMIT_DELAYED(5, d); // schedule with priority 5 (for now), maybe make configurable? + } + } + return ACTION_RELEASE; + } + if (pkt->isRouteDirect() && pkt->path_len >= PATH_HASH_SIZE) { if (self_id.isHashMatch(pkt->path) && allowPacketForward(pkt)) { if (_tables->hasSeen(pkt)) return ACTION_RELEASE; // don't retransmit! @@ -49,16 +73,6 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { pkt->path_len -= PATH_HASH_SIZE; memcpy(pkt->path, &pkt->path[PATH_HASH_SIZE], pkt->path_len); - if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE && pkt->payload_len + PATH_HASH_SIZE+1 < MAX_PACKET_PAYLOAD) { - if ((pkt->payload[0] & 3) == 0) { - // append our hash + SNR - pkt->payload_len += self_id.copyHashTo(&pkt->payload[pkt->payload_len]); - pkt->payload[pkt->payload_len++] = (int8_t) (pkt->getSNR()*4); - } else { - // unknown flags:type, don't append any info - } - } - uint32_t d = getDirectRetransmitDelay(pkt); return ACTION_RETRANSMIT_DELAYED(0, d); // Routed traffic is HIGHEST priority } @@ -80,16 +94,11 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { } break; } - case PAYLOAD_TYPE_TRACE: case PAYLOAD_TYPE_PATH: case PAYLOAD_TYPE_REQ: case PAYLOAD_TYPE_RESPONSE: case PAYLOAD_TYPE_TXT_MSG: { int i = 0; - if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) { - //uint8_t flags = pkt->payload[i]; // reserved for now - i++; // skip over - } uint8_t dest_hash = pkt->payload[i++]; uint8_t src_hash = pkt->payload[i++]; @@ -112,12 +121,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { // decrypt, checking MAC is valid uint8_t data[MAX_PACKET_PAYLOAD]; - int len; - if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) { - len = Utils::MACThenDecrypt(secret, data, macAndData, CIPHER_MAC_SIZE+CIPHER_BLOCK_SIZE); // encrypted part is fixed-len - } else { - len = Utils::MACThenDecrypt(secret, data, macAndData, pkt->payload_len - i); - } + int len = Utils::MACThenDecrypt(secret, data, macAndData, pkt->payload_len - i); if (len > 0) { // success! if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH) { int k = 0; @@ -133,8 +137,6 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { if (rpath) sendDirect(rpath, path, path_len); } } - } else if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) { - onPeerTraceRecv(pkt, j, secret, data); } else { onPeerDataRecv(pkt, pkt->getPayloadType(), j, secret, data, len); } @@ -265,16 +267,6 @@ DispatcherAction Mesh::routeRecvPacket(Packet* packet) { // append this node's hash to 'path' packet->path_len += self_id.copyHashTo(&packet->path[packet->path_len]); - if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE && (packet->payload[0] & 3) != 0) { - // flags:type must be zero (otherwise, some future/unknown sub-type) - return ACTION_RELEASE; // don't forward, just discard - } - - if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE && packet->payload_len + 1 < MAX_PACKET_PAYLOAD) { - // append packet SNR - packet->payload[packet->payload_len++] = (int8_t) (packet->getSNR()*4); - } - uint32_t d = getRetransmitDelay(packet); // as this propagates outwards, give it lower and lower priority return ACTION_RETRANSMIT_DELAYED(packet->path_len, d); // give priority to closer sources, than ones further away @@ -364,7 +356,7 @@ Packet* Mesh::createPathReturn(const uint8_t* dest_hash, const uint8_t* secret, } Packet* Mesh::createDatagram(uint8_t type, const Identity& dest, const uint8_t* secret, const uint8_t* data, size_t data_len) { - if (type == PAYLOAD_TYPE_TXT_MSG || type == PAYLOAD_TYPE_REQ || type == PAYLOAD_TYPE_RESPONSE || type == PAYLOAD_TYPE_TRACE) { + if (type == PAYLOAD_TYPE_TXT_MSG || type == PAYLOAD_TYPE_REQ || type == PAYLOAD_TYPE_RESPONSE) { if (data_len + CIPHER_MAC_SIZE + CIPHER_BLOCK_SIZE-1 > MAX_PACKET_PAYLOAD) return NULL; } else { return NULL; // invalid type @@ -378,9 +370,6 @@ Packet* Mesh::createDatagram(uint8_t type, const Identity& dest, const uint8_t* packet->header = (type << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later int len = 0; - if (type == PAYLOAD_TYPE_TRACE) { - packet->payload[len++] = 0; // reserved: flags:type - } len += dest.copyHashTo(&packet->payload[len]); // dest hash len += self_id.copyHashTo(&packet->payload[len]); // src hash len += Utils::encryptThenMAC(secret, &packet->payload[len], data, data_len); @@ -468,7 +457,28 @@ Packet* Mesh::createRawData(const uint8_t* data, size_t len) { return packet; } +Packet* Mesh::createTrace(uint32_t tag, uint32_t auth_code, uint8_t flags) { + Packet* packet = obtainNewPacket(); + if (packet == NULL) { + MESH_DEBUG_PRINTLN("%s Mesh::createTrace(): error, packet pool empty", getLogDateTime()); + return NULL; + } + packet->header = (PAYLOAD_TYPE_TRACE << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later + + memcpy(packet->payload, &tag, 4); + memcpy(&packet->payload[4], &auth_code, 4); + packet->payload[8] = flags; + packet->payload_len = 9; // NOTE: path will be appended to payload[] later + + return packet; +} + void Mesh::sendFlood(Packet* packet, uint32_t delay_millis) { + if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE) { + MESH_DEBUG_PRINTLN("%s Mesh::sendFlood(): TRACE type not suspported", getLogDateTime()); + return; + } + packet->header &= ~PH_ROUTE_MASK; packet->header |= ROUTE_TYPE_FLOOD; packet->path_len = 0; @@ -490,11 +500,20 @@ void Mesh::sendDirect(Packet* packet, const uint8_t* path, uint8_t path_len, uin packet->header &= ~PH_ROUTE_MASK; packet->header |= ROUTE_TYPE_DIRECT; - memcpy(packet->path, path, packet->path_len = path_len); + uint8_t pri; + if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE) { // TRACE packets are different + // for TRACE packets, path is appended to end of PAYLOAD. (path is used for SNR's) + memcpy(&packet->payload[packet->payload_len], path, path_len); + packet->payload_len += path_len; + packet->path_len = 0; + pri = 5; // maybe make this configurable + } else { + memcpy(packet->path, path, packet->path_len = path_len); + pri = 0; + } _tables->hasSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us - - sendPacket(packet, 0, delay_millis); + sendPacket(packet, pri, delay_millis); } void Mesh::sendZeroHop(Packet* packet, uint32_t delay_millis) { diff --git a/src/Mesh.h b/src/Mesh.h index aab082fa..cfacebc9 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -105,13 +105,16 @@ protected: virtual void onPeerDataRecv(Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) { } /** - * \brief A (now verified) TRACE packet has been received (by a known peer). - * NOTE: these can be received multiple times (per sender/msg-id), via different routes - * \param sender_idx index of peer, [0..n) where n is what searchPeersByHash() returned - * \param secret the pre-calculated shared-secret (handy for sending response packet) - * \param data decrypted data from payload (fixed length, one CIPHER_BLOCK) + * \brief A TRACE packet has been received. (and has reached the end of its given path) + * NOTE: this may have been initiated by another node. + * \param tag a random (unique-ish) tag set by initiator + * \param auth_code a code to authenticate the packet + * \param flags zero for now + * \param path_snrs single byte SNR*4 for each hop in the path + * \param path_hashes hashes if each repeater in the path + * \param path_len length of the path_snrs[] and path_hashes[] arrays */ - virtual void onPeerTraceRecv(Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* data) { } + virtual void onTraceRecv(Packet* packet, uint32_t tag, uint32_t auth_code, uint8_t flags, const uint8_t* path_snrs, const uint8_t* path_hashes, uint8_t path_len) { } /** * \brief A path TO peer (sender_idx) has been received. (also with optional 'extra' data encoded) @@ -192,6 +195,7 @@ public: Packet* createPathReturn(const uint8_t* dest_hash, const uint8_t* secret, const uint8_t* path, uint8_t path_len, uint8_t extra_type, const uint8_t*extra, size_t extra_len); Packet* createPathReturn(const Identity& dest, const uint8_t* secret, const uint8_t* path, uint8_t path_len, uint8_t extra_type, const uint8_t*extra, size_t extra_len); Packet* createRawData(const uint8_t* data, size_t len); + Packet* createTrace(uint32_t tag, uint32_t auth_code, uint8_t flags = 0); /** * \brief send a locally-generated Packet with flood routing @@ -207,6 +211,7 @@ public: * \brief send a locally-generated Packet to just neigbor nodes (zero hops) */ void sendZeroHop(Packet* packet, uint32_t delay_millis=0); + }; } diff --git a/src/Packet.cpp b/src/Packet.cpp index 82a73339..71f89c1f 100644 --- a/src/Packet.cpp +++ b/src/Packet.cpp @@ -14,11 +14,7 @@ void Packet::calculatePacketHash(uint8_t* hash) const { SHA256 sha; uint8_t t = getPayloadType(); sha.update(&t, 1); - if (t == PAYLOAD_TYPE_TRACE) { - sha.update(payload, 3+CIPHER_MAC_SIZE+CIPHER_BLOCK_SIZE); // the 'content' part of TRACE packets is just the fixed-len encrypted part - } else { - sha.update(payload, payload_len); - } + sha.update(payload, payload_len); sha.finalize(hash, MAX_HASH_SIZE); } diff --git a/src/helpers/BaseChatMesh.cpp b/src/helpers/BaseChatMesh.cpp index 813bb8e9..eb6116e7 100644 --- a/src/helpers/BaseChatMesh.cpp +++ b/src/helpers/BaseChatMesh.cpp @@ -166,50 +166,6 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender } } -void BaseChatMesh::onPeerTraceRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* data) { - int i = matching_peer_indexes[sender_idx]; - if (i < 0 || i >= num_contacts) { - MESH_DEBUG_PRINTLN("onPeerTraceRecv: Invalid sender idx: %d", i); - return; - } - - if ((packet->payload[0] & 3) != 0) { - MESH_DEBUG_PRINTLN("onPeerTraceRecv: unknown TRACE sub-type: %u", (uint32_t)packet->payload[0]); - return; - } - - ContactInfo& from = contacts[i]; - - uint32_t timestamp; - memcpy(×tamp, data, 4); // timestamp (by sender's RTC clock - which could be wrong) - uint8_t sender_flags = data[4]; - - int j = 3 + CIPHER_MAC_SIZE + CIPHER_BLOCK_SIZE; // skip fixed-len part - - uint8_t path_hashes[64]; - int8_t path_snr[65]; - uint16_t len; - if (packet->isRouteFlood()) { - memcpy(path_hashes, packet->path, len = packet->path_len); - memset(path_snr, 0, sizeof(path_snr)); - memcpy(path_snr, &packet->payload[j], packet->payload_len - j); // 'track' should just contain SNRs - } else { - len = 0; - while (j + 1 < packet->payload_len) { - path_hashes[len] = packet->payload[j++]; // pairs of Hash + SNR - path_snr[len] = packet->payload[j++]; - len++; - } - } - path_snr[len] = (int8_t)(packet->getSNR()*4); // also include last hop (to this node) - - onContactTraceRecv(from, timestamp, path_hashes, path_snr, len); - - if (sender_flags & 1) { // the 'wants reply' flag - // TODO: send a TRACE packet back - } -} - bool BaseChatMesh::onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) { int i = matching_peer_indexes[sender_idx]; if (i < 0 || i >= num_contacts) { @@ -304,25 +260,6 @@ int BaseChatMesh::sendMessage(const ContactInfo& recipient, uint32_t timestamp, return rc; } -bool BaseChatMesh::sendContactTraceDirect(const ContactInfo& recipient, bool wantReply) { - if (recipient.out_path_len < 0) return false; // Error: no known path - - uint8_t temp[CIPHER_BLOCK_SIZE]; - memset(temp, 0, sizeof(temp)); - - uint32_t timestamp = getRTCClock()->getCurrentTime(); - memcpy(temp, ×tamp, 4); - temp[4] = wantReply ? 1 : 0; - // TODO: any other data to encrypt?? - - auto pkt = createDatagram(PAYLOAD_TYPE_TRACE, recipient.id, recipient.shared_secret, temp, sizeof(temp)); - if (pkt) { - sendDirect(pkt, recipient.out_path, recipient.out_path_len); - return true; // success - } - return false; // error -} - int BaseChatMesh::sendCommandData(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char* text, uint32_t& est_timeout) { int text_len = strlen(text); if (text_len > MAX_TEXT_LEN) return MSG_SEND_FAILED; diff --git a/src/helpers/BaseChatMesh.h b/src/helpers/BaseChatMesh.h index 6a577828..30598f6c 100644 --- a/src/helpers/BaseChatMesh.h +++ b/src/helpers/BaseChatMesh.h @@ -114,7 +114,6 @@ protected: virtual void onSendTimeout() = 0; virtual void onChannelMessageRecv(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t timestamp, const char *text) = 0; virtual void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) = 0; - virtual void onContactTraceRecv(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t hash[], int8_t snr[], uint8_t path_len) = 0; // storage concepts, for sub-classes to override/implement virtual int getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) { return 0; } // not implemented @@ -126,7 +125,6 @@ protected: void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override; void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override; bool onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override; - void onPeerTraceRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* data) override; void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) override; #ifdef MAX_GROUP_CHANNELS int searchChannelsByHash(const uint8_t* hash, mesh::GroupChannel channels[], int max_matches) override; @@ -151,7 +149,6 @@ public: bool shareContactZeroHop(const ContactInfo& contact); uint8_t exportContact(const ContactInfo& contact, uint8_t dest_buf[]); bool importContact(const uint8_t src_buf[], uint8_t len); - bool sendContactTraceDirect(const ContactInfo& recipient, bool wantReply); void resetPathTo(ContactInfo& recipient); void scanRecentContacts(int last_n, ContactVisitor* visitor); ContactInfo* searchContactsByPrefix(const char* name_prefix); From 807b9bdc1987293b58b077a783db298d5c596afb Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Mon, 17 Mar 2025 18:15:38 +1100 Subject: [PATCH 17/28] * companion support for TRACE packets. (CMD_SEND_TRACE_PATH, PUSH_CODE_TRACE_DATA) --- examples/companion_radio/main.cpp | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index d06b4f12..56492b92 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -175,6 +175,7 @@ static uint32_t _atoi(const char* sp) { #define CMD_SIGN_START 33 #define CMD_SIGN_DATA 34 #define CMD_SIGN_FINISH 35 +#define CMD_SEND_TRACE_PATH 36 #define RESP_CODE_OK 0 #define RESP_CODE_ERR 1 @@ -208,6 +209,7 @@ static uint32_t _atoi(const char* sp) { #define PUSH_CODE_LOGIN_FAIL 0x86 #define PUSH_CODE_STATUS_RESPONSE 0x87 #define PUSH_CODE_LOG_RX_DATA 0x88 +#define PUSH_CODE_TRACE_DATA 0x89 /* -------------------------------------------------------------------------------------- */ @@ -710,6 +712,25 @@ protected: } } + void onTraceRecv(mesh::Packet* packet, uint32_t tag, uint32_t auth_code, uint8_t flags, const uint8_t* path_snrs, const uint8_t* path_hashes, uint8_t path_len) override { + int i = 0; + out_frame[i++] = PUSH_CODE_TRACE_DATA; + out_frame[i++] = 0; // reserved + out_frame[i++] = path_len; + out_frame[i++] = flags; + memcpy(&out_frame[i], &tag, 4); i += 4; + memcpy(&out_frame[i], &auth_code, 4); i += 4; + memcpy(&out_frame[i], path_hashes, path_len); i += path_len; + memcpy(&out_frame[i], path_snrs, path_len); i += path_len; + out_frame[i++] = (int8_t)(_radio->getLastSNR() * 4); // extra/final SNR (to this node) + + if (_serial->isConnected()) { + _serial->writeFrame(out_frame, i); + } else { + MESH_DEBUG_PRINTLN("onTraceRecv(), data received while app offline"); + } + } + uint32_t calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const override { return SEND_TIMEOUT_BASE_MILLIS + (FLOOD_SEND_TIMEOUT_FACTOR * pkt_airtime_millis); } @@ -1337,6 +1358,18 @@ public: } else { writeErrFrame(); } + } else if (cmd_frame[0] == CMD_SEND_TRACE_PATH && len > 10 && len - 10 < MAX_PATH_SIZE) { + uint32_t tag, auth; + memcpy(&tag, &cmd_frame[1], 4); + memcpy(&auth, &cmd_frame[5], 4); + auto pkt = createTrace(tag, auth, cmd_frame[9]); + if (pkt) { + uint8_t path_len = len - 10; + sendDirect(pkt, &cmd_frame[10], path_len); + writeOKFrame(); + } else { + writeErrFrame(); + } } else { writeErrFrame(); MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]); From 691c135c22f257cc9cebbeb0490ce71d165c15d6 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Mon, 17 Mar 2025 19:35:08 +1100 Subject: [PATCH 18/28] * workaround for TRACE packets so they can follow a return path --- src/Packet.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Packet.cpp b/src/Packet.cpp index 71f89c1f..e338b60d 100644 --- a/src/Packet.cpp +++ b/src/Packet.cpp @@ -14,6 +14,9 @@ void Packet::calculatePacketHash(uint8_t* hash) const { SHA256 sha; uint8_t t = getPayloadType(); sha.update(&t, 1); + if (t == PAYLOAD_TYPE_TRACE) { + sha.update(&path_len, sizeof(path_len)); // CAVEAT: TRACE packets can revisit same node on return path + } sha.update(payload, payload_len); sha.finalize(hash, MAX_HASH_SIZE); } From 13679f9ff16f64d7241d25d2f65ffb02ec1289f8 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Tue, 18 Mar 2025 00:14:57 +1100 Subject: [PATCH 19/28] * CMD_SEND_TRACE_PATH, now replies with RESP_CODE_SENT --- examples/companion_radio/main.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 56492b92..ad133a14 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -1366,7 +1366,15 @@ public: if (pkt) { uint8_t path_len = len - 10; sendDirect(pkt, &cmd_frame[10], path_len); - writeOKFrame(); + + uint32_t t = _radio->getEstAirtimeFor(pkt->payload_len + pkt->path_len + 2); + uint32_t est_timeout = calcDirectTimeoutMillisFor(t, path_len); + + out_frame[0] = RESP_CODE_SENT; + out_frame[1] = 0; + memcpy(&out_frame[2], &tag, 4); + memcpy(&out_frame[6], &est_timeout, 4); + _serial->writeFrame(out_frame, 10); } else { writeErrFrame(); } From f08a30cf24364bd252e8b9ca79487c6fe0bc6714 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Tue, 18 Mar 2025 15:27:55 +1100 Subject: [PATCH 20/28] * companion: RESP_CODE_ERR now has err_code byte --- examples/companion_radio/main.cpp | 98 ++++++++++++++++++------------- 1 file changed, 57 insertions(+), 41 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 858ca018..9a1be2bd 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -212,6 +212,13 @@ static uint32_t _atoi(const char* sp) { #define PUSH_CODE_LOG_RX_DATA 0x88 #define PUSH_CODE_TRACE_DATA 0x89 +#define ERR_CODE_UNSUPPORTED_CMD 1 +#define ERR_CODE_NOT_FOUND 2 +#define ERR_CODE_TABLE_FULL 3 +#define ERR_CODE_BAD_STATE 4 +#define ERR_CODE_FILE_IO_ERROR 5 +#define ERR_CODE_ILLEGAL_ARG 6 + /* -------------------------------------------------------------------------------------- */ #define MAX_SIGN_DATA_LEN (8*1024) // 8K @@ -442,10 +449,11 @@ class MyMesh : public BaseChatMesh { buf[0] = RESP_CODE_OK; _serial->writeFrame(buf, 1); } - void writeErrFrame() { - uint8_t buf[1]; + void writeErrFrame(uint8_t err_code) { + uint8_t buf[2]; buf[0] = RESP_CODE_ERR; - _serial->writeFrame(buf, 1); + buf[1] = err_code; + _serial->writeFrame(buf, 2); } void writeDisabledFrame() { @@ -958,7 +966,7 @@ public: } // TODO: add expected ACK to table if (result == MSG_SEND_FAILED) { - writeErrFrame(); + writeErrFrame(ERR_CODE_TABLE_FULL); } else { if (expected_ack) { expected_ack_table[next_ack_idx].msg_sent = _ms->getMillis(); // add to circular table @@ -973,7 +981,7 @@ public: _serial->writeFrame(out_frame, 10); } } else { - writeErrFrame(); // unknown recipient, or unsuported TXT_TYPE_* + writeErrFrame(recipient == NULL ? ERR_CODE_NOT_FOUND : ERR_CODE_UNSUPPORTED_CMD); // unknown recipient, or unsuported TXT_TYPE_* } } else if (cmd_frame[0] == CMD_SEND_CHANNEL_TXT_MSG) { // send GroupChannel msg int i = 1; @@ -983,16 +991,20 @@ public: memcpy(&msg_timestamp, &cmd_frame[i], 4); i += 4; const char *text = (char *) &cmd_frame[i]; - ChannelDetails channel; - bool success = getChannel(channel_idx, channel); - if (success && txt_type == TXT_TYPE_PLAIN && sendGroupMessage(msg_timestamp, channel.channel, _prefs.node_name, text, len - i)) { - writeOKFrame(); + if (txt_type != TXT_TYPE_PLAIN) { + writeErrFrame(ERR_CODE_UNSUPPORTED_CMD); } else { - writeErrFrame(); + ChannelDetails channel; + bool success = getChannel(channel_idx, channel); + if (success && sendGroupMessage(msg_timestamp, channel.channel, _prefs.node_name, text, len - i)) { + writeOKFrame(); + } else { + writeErrFrame(ERR_CODE_NOT_FOUND); // bad channel_idx + } } } else if (cmd_frame[0] == CMD_GET_CONTACTS) { // get Contact list if (_iter_started) { - writeErrFrame(); // iterator is currently busy + writeErrFrame(ERR_CODE_BAD_STATE); // iterator is currently busy } else { if (len >= 5) { // has optional 'since' param memcpy(&_iter_filter_since, &cmd_frame[1], 4); @@ -1031,7 +1043,7 @@ public: savePrefs(); writeOKFrame(); } else { - writeErrFrame(); // invalid geo coordinate + writeErrFrame(ERR_CODE_ILLEGAL_ARG); // invalid geo coordinate } } else if (cmd_frame[0] == CMD_GET_DEVICE_TIME) { uint8_t reply[5]; @@ -1047,7 +1059,7 @@ public: getRTCClock()->setCurrentTime(secs); writeOKFrame(); } else { - writeErrFrame(); + writeErrFrame(ERR_CODE_ILLEGAL_ARG); } } else if (cmd_frame[0] == CMD_SEND_SELF_ADVERT) { auto pkt = createSelfAdvert(_prefs.node_name, _prefs.node_lat, _prefs.node_lon); @@ -1059,7 +1071,7 @@ public: } writeOKFrame(); } else { - writeErrFrame(); + writeErrFrame(ERR_CODE_TABLE_FULL); } } else if (cmd_frame[0] == CMD_RESET_PATH && len >= 1+32) { uint8_t* pub_key = &cmd_frame[1]; @@ -1070,7 +1082,7 @@ public: saveContacts(); writeOKFrame(); } else { - writeErrFrame(); // unknown contact + writeErrFrame(ERR_CODE_NOT_FOUND); // unknown contact } } else if (cmd_frame[0] == CMD_ADD_UPDATE_CONTACT && len >= 1+32+2+1) { uint8_t* pub_key = &cmd_frame[1]; @@ -1089,7 +1101,7 @@ public: saveContacts(); writeOKFrame(); } else { - writeErrFrame(); // table is full! + writeErrFrame(ERR_CODE_TABLE_FULL); } } } else if (cmd_frame[0] == CMD_REMOVE_CONTACT) { @@ -1099,15 +1111,19 @@ public: saveContacts(); writeOKFrame(); } else { - writeErrFrame(); // not found, or unable to remove + writeErrFrame(ERR_CODE_NOT_FOUND); // not found, or unable to remove } } else if (cmd_frame[0] == CMD_SHARE_CONTACT) { uint8_t* pub_key = &cmd_frame[1]; ContactInfo* recipient = lookupContactByPubKey(pub_key, PUB_KEY_SIZE); - if (recipient && shareContactZeroHop(*recipient)) { - writeOKFrame(); + if (recipient) { + if (shareContactZeroHop(*recipient)) { + writeOKFrame(); + } else { + writeErrFrame(ERR_CODE_TABLE_FULL); // unable to send + } } else { - writeErrFrame(); // not found, or unable to send + writeErrFrame(ERR_CODE_NOT_FOUND); } } else if (cmd_frame[0] == CMD_GET_CONTACT_BY_KEY) { uint8_t* pub_key = &cmd_frame[1]; @@ -1115,7 +1131,7 @@ public: if (contact) { writeContactRespFrame(RESP_CODE_CONTACT, *contact); } else { - writeErrFrame(); // not found + writeErrFrame(ERR_CODE_NOT_FOUND); // not found } } else if (cmd_frame[0] == CMD_EXPORT_CONTACT) { if (len < 1 + PUB_KEY_SIZE) { @@ -1127,7 +1143,7 @@ public: releasePacket(pkt); // undo the obtainNewPacket() _serial->writeFrame(out_frame, out_len + 1); } else { - writeErrFrame(); // Error + writeErrFrame(ERR_CODE_TABLE_FULL); // Error } } else { uint8_t* pub_key = &cmd_frame[1]; @@ -1137,14 +1153,14 @@ public: out_frame[0] = RESP_CODE_EXPORT_CONTACT; _serial->writeFrame(out_frame, out_len + 1); } else { - writeErrFrame(); // not found + writeErrFrame(ERR_CODE_NOT_FOUND); // not found } } } else if (cmd_frame[0] == CMD_IMPORT_CONTACT && len > 2+32+64) { if (importContact(&cmd_frame[1], len - 1)) { writeOKFrame(); } else { - writeErrFrame(); + writeErrFrame(ERR_CODE_ILLEGAL_ARG); } } else if (cmd_frame[0] == CMD_SYNC_NEXT_MESSAGE) { int out_len; @@ -1182,11 +1198,11 @@ public: writeOKFrame(); } else { MESH_DEBUG_PRINTLN("Error: CMD_SET_RADIO_PARAMS: f=%d, bw=%d, sf=%d, cr=%d", freq, bw, (uint32_t)sf, (uint32_t)cr); - writeErrFrame(); + writeErrFrame(ERR_CODE_ILLEGAL_ARG); } } else if (cmd_frame[0] == CMD_SET_RADIO_TX_POWER) { if (cmd_frame[1] > MAX_LORA_TX_POWER) { - writeErrFrame(); + writeErrFrame(ERR_CODE_ILLEGAL_ARG); } else { _prefs.tx_power_dbm = cmd_frame[1]; savePrefs(); @@ -1227,7 +1243,7 @@ public: self_id = identity; writeOKFrame(); } else { - writeErrFrame(); + writeErrFrame(ERR_CODE_FILE_IO_ERROR); } #else writeDisabledFrame(); @@ -1242,10 +1258,10 @@ public: sendDirect(pkt, path, path_len); writeOKFrame(); } else { - writeErrFrame(); + writeErrFrame(ERR_CODE_TABLE_FULL); } } else { - writeErrFrame(); // flood, not supported (yet) + writeErrFrame(ERR_CODE_UNSUPPORTED_CMD); // flood, not supported (yet) } } else if (cmd_frame[0] == CMD_SEND_LOGIN && len >= 1+PUB_KEY_SIZE) { uint8_t* pub_key = &cmd_frame[1]; @@ -1256,7 +1272,7 @@ public: uint32_t est_timeout; int result = sendLogin(*recipient, password, est_timeout); if (result == MSG_SEND_FAILED) { - writeErrFrame(); + writeErrFrame(ERR_CODE_TABLE_FULL); } else { pending_status = 0; memcpy(&pending_login, recipient->id.pub_key, 4); // match this to onContactResponse() @@ -1267,7 +1283,7 @@ public: _serial->writeFrame(out_frame, 10); } } else { - writeErrFrame(); // contact not found + writeErrFrame(ERR_CODE_NOT_FOUND); // contact not found } } else if (cmd_frame[0] == CMD_SEND_STATUS_REQ && len >= 1+PUB_KEY_SIZE) { uint8_t* pub_key = &cmd_frame[1]; @@ -1276,7 +1292,7 @@ public: uint32_t est_timeout; int result = sendStatusRequest(*recipient, est_timeout); if (result == MSG_SEND_FAILED) { - writeErrFrame(); + writeErrFrame(ERR_CODE_TABLE_FULL); } else { pending_login = 0; memcpy(&pending_status, recipient->id.pub_key, 4); // match this to onContactResponse() @@ -1287,14 +1303,14 @@ public: _serial->writeFrame(out_frame, 10); } } else { - writeErrFrame(); // contact not found + writeErrFrame(ERR_CODE_NOT_FOUND); // contact not found } } else if (cmd_frame[0] == CMD_HAS_CONNECTION && len >= 1+PUB_KEY_SIZE) { uint8_t* pub_key = &cmd_frame[1]; if (hasConnectionTo(pub_key)) { writeOKFrame(); } else { - writeErrFrame(); + writeErrFrame(ERR_CODE_NOT_FOUND); } } else if (cmd_frame[0] == CMD_LOGOUT && len >= 1+PUB_KEY_SIZE) { uint8_t* pub_key = &cmd_frame[1]; @@ -1311,10 +1327,10 @@ public: memcpy(&out_frame[i], channel.channel.secret, 16); i += 16; // NOTE: only 128-bit supported _serial->writeFrame(out_frame, i); } else { - writeErrFrame(); + writeErrFrame(ERR_CODE_NOT_FOUND); } } else if (cmd_frame[0] == CMD_SET_CHANNEL && len >= 2+32+32) { - writeErrFrame(); // not supported (yet) + writeErrFrame(ERR_CODE_UNSUPPORTED_CMD); // not supported (yet) } else if (cmd_frame[0] == CMD_SET_CHANNEL && len >= 2+32+16) { uint8_t channel_idx = cmd_frame[1]; ChannelDetails channel; @@ -1325,7 +1341,7 @@ public: saveChannels(); writeOKFrame(); } else { - writeErrFrame(); + writeErrFrame(ERR_CODE_NOT_FOUND); // bad channel_idx } } else if (cmd_frame[0] == CMD_SIGN_START) { out_frame[0] = RESP_CODE_SIGN_START; @@ -1341,7 +1357,7 @@ public: sign_data_len = 0; } else if (cmd_frame[0] == CMD_SIGN_DATA && len > 1) { if (sign_data == NULL || sign_data_len + (len - 1) > MAX_SIGN_DATA_LEN) { - writeErrFrame(); // error: too long + writeErrFrame(sign_data == NULL ? ERR_CODE_BAD_STATE : ERR_CODE_TABLE_FULL); // error: too long } else { memcpy(&sign_data[sign_data_len], &cmd_frame[1], len - 1); sign_data_len += (len - 1); @@ -1357,7 +1373,7 @@ public: out_frame[0] = RESP_CODE_SIGNATURE; _serial->writeFrame(out_frame, 1 + SIGNATURE_SIZE); } else { - writeErrFrame(); + writeErrFrame(ERR_CODE_BAD_STATE); } } else if (cmd_frame[0] == CMD_SEND_TRACE_PATH && len > 10 && len - 10 < MAX_PATH_SIZE) { uint32_t tag, auth; @@ -1377,10 +1393,10 @@ public: memcpy(&out_frame[6], &est_timeout, 4); _serial->writeFrame(out_frame, 10); } else { - writeErrFrame(); + writeErrFrame(ERR_CODE_TABLE_FULL); } } else { - writeErrFrame(); + writeErrFrame(ERR_CODE_UNSUPPORTED_CMD); MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]); } } From 50b62c9252bc96957582db4b8659e4e39115fa3a Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Tue, 18 Mar 2025 16:49:40 +1100 Subject: [PATCH 21/28] * room server: now handles REQ_TYPE_GET_STATUS, replies with ServerStats (same as RepeaterStats, with extra fields: n_posted, n_post_push) --- examples/simple_room_server/main.cpp | 109 ++++++++++++++++++++++----- 1 file changed, 89 insertions(+), 20 deletions(-) diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index 3f510789..9e21402b 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -162,6 +162,23 @@ struct PostInfo { #define RESP_SERVER_LOGIN_OK 0 // response to ANON_REQ +struct ServerStats { + uint16_t batt_milli_volts; + uint16_t curr_tx_queue_len; + uint16_t curr_free_queue_len; + int16_t last_rssi; + uint32_t n_packets_recv; + uint32_t n_packets_sent; + uint32_t total_air_time_secs; + uint32_t total_up_time_secs; + uint32_t n_sent_flood, n_sent_direct; + uint32_t n_recv_flood, n_recv_direct; + uint16_t n_full_events; + int16_t last_snr; // x 4 + uint16_t n_direct_dups, n_flood_dups; + uint16_t n_posted, n_post_push; +}; + class MyMesh : public mesh::Mesh, public CommonCLICallbacks { RadioLibWrapper* my_radio; FILESYSTEM* _fs; @@ -174,6 +191,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks { int num_clients; ClientInfo known_clients[MAX_CLIENTS]; unsigned long next_push; + uint16_t _num_posted, _num_post_pushes; int next_client_idx; // for round-robin polling int next_post_idx; PostInfo posts[MAX_UNSYNCED_POSTS]; // cyclic queue @@ -220,6 +238,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks { next_post_idx = (next_post_idx + 1) % MAX_UNSYNCED_POSTS; next_push = futureMillis(PUSH_NOTIFY_DELAY_MILLIS); + _num_posted++; // stats } void pushPostToClient(ClientInfo* client, PostInfo& post) { @@ -246,6 +265,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks { sendDirect(reply, client->out_path, client->out_path_len); client->ack_timeout = futureMillis(PUSH_TIMEOUT_BASE + PUSH_ACK_TIMEOUT_FACTOR * (client->out_path_len + 1)); } + _num_post_pushes++; // stats } else { client->pending_ack = 0; MESH_DEBUG_PRINTLN("Unable to push post to client"); @@ -495,33 +515,81 @@ protected: } else if (type == PAYLOAD_TYPE_REQ && len >= 5) { uint32_t sender_timestamp; memcpy(&sender_timestamp, data, 4); // timestamp (by sender's RTC clock - which could be wrong) - if (data[4] == REQ_TYPE_KEEP_ALIVE && packet->isRouteDirect()) { // request type - uint32_t forceSince = 0; - if (len >= 9) { // optional - last post_timestamp client received - memcpy(&forceSince, &data[5], 4); // NOTE: this may be 0, if part of decrypted PADDING! - } else { - memcpy(&data[5], &forceSince, 4); // make sure there are zeroes in payload (for ack_hash calc below) - } - if (forceSince > 0) { - client->sync_since = forceSince; // force-update the 'sync since' - } + if (sender_timestamp < client->last_timestamp) { // prevent replay attacks + MESH_DEBUG_PRINTLN("onPeerDataRecv: possible replay attack detected"); + } else { + client->last_timestamp = sender_timestamp; uint32_t now = getRTCClock()->getCurrentTime(); client->last_activity = now; // <-- THIS will keep client connection alive client->push_failures = 0; // reset so push can resume (if prev failed) - client->pending_ack = 0; - // TODO: Throttle KEEP_ALIVE requests! - // if client sends too quickly, evict() + if (data[4] == REQ_TYPE_KEEP_ALIVE && packet->isRouteDirect()) { // request type + uint32_t forceSince = 0; + if (len >= 9) { // optional - last post_timestamp client received + memcpy(&forceSince, &data[5], 4); // NOTE: this may be 0, if part of decrypted PADDING! + } else { + memcpy(&data[5], &forceSince, 4); // make sure there are zeroes in payload (for ack_hash calc below) + } + if (forceSince > 0) { + client->sync_since = forceSince; // force-update the 'sync since' + } - // RULE: only send keep_alive response DIRECT! - if (client->out_path_len >= 0) { - uint32_t ack_hash; // calc ACK to prove to sender that we got request - mesh::Utils::sha256((uint8_t *) &ack_hash, 4, data, 9, client->id.pub_key, PUB_KEY_SIZE); + client->pending_ack = 0; - auto reply = createAck(ack_hash); - if (reply) { - sendDirect(reply, client->out_path, client->out_path_len); + // TODO: Throttle KEEP_ALIVE requests! + // if client sends too quickly, evict() + + // RULE: only send keep_alive response DIRECT! + if (client->out_path_len >= 0) { + uint32_t ack_hash; // calc ACK to prove to sender that we got request + mesh::Utils::sha256((uint8_t *) &ack_hash, 4, data, 9, client->id.pub_key, PUB_KEY_SIZE); + + auto reply = createAck(ack_hash); + if (reply) { + sendDirect(reply, client->out_path, client->out_path_len); + } + } + } else if (data[4] == REQ_TYPE_GET_STATUS) { + ServerStats stats; + stats.batt_milli_volts = board.getBattMilliVolts(); + stats.curr_tx_queue_len = _mgr->getOutboundCount(); + stats.curr_free_queue_len = _mgr->getFreeCount(); + stats.last_rssi = (int16_t) my_radio->getLastRSSI(); + stats.n_packets_recv = my_radio->getPacketsRecv(); + stats.n_packets_sent = my_radio->getPacketsSent(); + stats.total_air_time_secs = getTotalAirTime() / 1000; + stats.total_up_time_secs = _ms->getMillis() / 1000; + stats.n_sent_flood = getNumSentFlood(); + stats.n_sent_direct = getNumSentDirect(); + stats.n_recv_flood = getNumRecvFlood(); + stats.n_recv_direct = getNumRecvDirect(); + stats.n_full_events = getNumFullEvents(); + stats.last_snr = (int16_t)(my_radio->getLastSNR() * 4); + stats.n_direct_dups = ((SimpleMeshTables *)getTables())->getNumDirectDups(); + stats.n_flood_dups = ((SimpleMeshTables *)getTables())->getNumFloodDups(); + stats.n_posted = _num_posted; + stats.n_post_push = _num_post_pushes; + + now = getRTCClock()->getCurrentTimeUnique(); + memcpy(reply_data, &now, 4); // response packets always prefixed with timestamp + memcpy(&reply_data[4], &stats, sizeof(stats)); + uint8_t reply_len = 4 + sizeof(stats); + + if (packet->isRouteFlood()) { + // let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response + mesh::Packet* path = createPathReturn(client->id, secret, packet->path, packet->path_len, + PAYLOAD_TYPE_RESPONSE, reply_data, reply_len); + if (path) sendFlood(path); + } else { + mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len); + if (reply) { + if (client->out_path_len >= 0) { // we have an out_path, so send DIRECT + sendDirect(reply, client->out_path, client->out_path_len); + } else { + sendFlood(reply); + } + } } } } @@ -589,6 +657,7 @@ public: next_client_idx = 0; next_push = 0; memset(posts, 0, sizeof(posts)); + _num_posted = _num_post_pushes = 0; } CommonCLI* getCLI() { return &_cli; } From d21274db41c8818ab9907611cab9d01b51ebd61a Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Tue, 18 Mar 2025 21:34:32 +1100 Subject: [PATCH 22/28] * TBeam: minor refactor. --- src/helpers/TBeamBoard.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/helpers/TBeamBoard.h b/src/helpers/TBeamBoard.h index a6cff678..fc0d3b73 100644 --- a/src/helpers/TBeamBoard.h +++ b/src/helpers/TBeamBoard.h @@ -7,7 +7,6 @@ // Defined using AXP2102 #define XPOWERS_CHIP_AXP2101 -XPowersAXP2101 power; // LoRa radio module pins for TBeam #define P_LORA_DIO_0 26 @@ -29,6 +28,8 @@ XPowersAXP2101 power; #include class TBeamBoard : public ESP32Board { + XPowersAXP2101 power; + public: void begin() { ESP32Board::begin(); From 38667dabb1f9257b35e635fb57ef7aa94a284655 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Tue, 18 Mar 2025 23:57:04 +1100 Subject: [PATCH 23/28] * refactored platformio.ini, breaking up into variants/*.ini files --- platformio.ini | 1203 +-------------------- variants/heltec_v2/platformio.ini | 101 ++ variants/heltec_v3/platformio.ini | 173 +++ variants/lilygo_t3s3/platformio.ini | 116 ++ variants/lilygo_tbeam/platformio.ini | 36 + variants/lilygo_tlora_v2_1/platformio.ini | 111 ++ variants/promicro_nrf52840/platformio.ini | 173 +++ variants/rak4631/platformio.ini | 102 ++ variants/station_g2/platformio.ini | 49 + variants/t1000-e/platformio.ini | 51 + variants/t114/platformio.ini | 76 ++ variants/techo/platformio.ini | 72 ++ variants/xiao_c3/platformio.ini | 50 + variants/xiao_s3_wio/platformio.ini | 67 ++ 14 files changed, 1183 insertions(+), 1197 deletions(-) create mode 100644 variants/heltec_v2/platformio.ini create mode 100644 variants/heltec_v3/platformio.ini create mode 100644 variants/lilygo_t3s3/platformio.ini create mode 100644 variants/lilygo_tbeam/platformio.ini create mode 100644 variants/lilygo_tlora_v2_1/platformio.ini create mode 100644 variants/promicro_nrf52840/platformio.ini create mode 100644 variants/rak4631/platformio.ini create mode 100644 variants/station_g2/platformio.ini create mode 100644 variants/t1000-e/platformio.ini create mode 100644 variants/t114/platformio.ini create mode 100644 variants/techo/platformio.ini create mode 100644 variants/xiao_c3/platformio.ini create mode 100644 variants/xiao_s3_wio/platformio.ini diff --git a/platformio.ini b/platformio.ini index 6f163720..e0f57cc4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -8,6 +8,10 @@ ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html +[platformio] +extra_configs = + variants/*/platformio.ini + [arduino_base] framework = arduino monitor_speed = 115200 @@ -26,6 +30,8 @@ build_src_filter = +<*.cpp> + +; ----------------- ESP32 --------------------- + [esp32_base] extends = arduino_base platform = espressif32 @@ -35,723 +41,6 @@ build_flags = ${arduino_base.build_flags} ; -D ESP32_CPU_FREQ=80 ; change it to your need build_src_filter = ${arduino_base.build_src_filter} -; ================ -[Heltec_lora32_v2] -extends = esp32_base -board = heltec_wifi_lora_32_V2 ; heltec_wifi_lora_32_V2 -build_flags = - ${esp32_base.build_flags} - -D HELTEC_LORA_V2 - -D PIN_BOARD_SDA=4 - -D PIN_BOARD_SCL=15 - -D PIN_USER_BTN=0 - -D PIN_OLED_RESET=16 - -D RADIO_CLASS=CustomSX1276 - -D WRAPPER_CLASS=CustomSX1276Wrapper - -D LORA_TX_POWER=20 - -D P_LORA_TX_LED=25 -build_src_filter = ${esp32_base.build_src_filter} -lib_deps = - ${esp32_base.lib_deps} - adafruit/Adafruit SSD1306 @ ^2.5.13 - -[env:Heltec_v2_repeater] -extends = Heltec_lora32_v2 -build_flags = - ${Heltec_lora32_v2.build_flags} - -D DISPLAY_CLASS=SSD1306Display - -D ADVERT_NAME='"Heltec Repeater"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Heltec_lora32_v2.build_src_filter} - +<../examples/simple_repeater> - + - -[env:Heltec_v2_room_server] -extends = Heltec_lora32_v2 -build_flags = - ${Heltec_lora32_v2.build_flags} - -D DISPLAY_CLASS=SSD1306Display - -D ADVERT_NAME='"Heltec Room"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' - -D ROOM_PASSWORD='"hello"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Heltec_lora32_v2.build_src_filter} - + - +<../examples/simple_room_server> - -[env:Heltec_v2_terminal_chat] -extends = Heltec_lora32_v2 -build_flags = - ${Heltec_lora32_v2.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Heltec_lora32_v2.build_src_filter} - +<../examples/simple_secure_chat/main.cpp> -lib_deps = - ${Heltec_lora32_v2.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[env:Heltec_v2_companion_radio_usb] -extends = Heltec_lora32_v2 -build_flags = - ${Heltec_lora32_v2.build_flags} - -D DISPLAY_CLASS=SSD1306Display - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 -; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 -; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 -build_src_filter = ${Heltec_lora32_v2.build_src_filter} - + - + - +<../examples/companion_radio> -lib_deps = - ${Heltec_lora32_v2.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[env:Heltec_v2_companion_radio_ble] -extends = Heltec_lora32_v2 -build_flags = - ${Heltec_lora32_v2.build_flags} - -D DISPLAY_CLASS=SSD1306Display - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 - -D BLE_PIN_CODE=0 - -D BLE_DEBUG_LOGGING=1 -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Heltec_lora32_v2.build_src_filter} - + - + - +<../examples/companion_radio> -lib_deps = - ${Heltec_lora32_v2.lib_deps} - densaugeo/base64 @ ~1.4.0 - -; ================ -[Heltec_lora32_v3] -extends = esp32_base -board = esp32-s3-devkitc-1 -build_flags = - ${esp32_base.build_flags} - -D HELTEC_LORA_V3 - -D RADIO_CLASS=CustomSX1262 - -D WRAPPER_CLASS=CustomSX1262Wrapper - -D LORA_TX_POWER=22 - -D P_LORA_TX_LED=35 - -D PIN_BOARD_SDA=17 - -D PIN_BOARD_SCL=18 - -D PIN_USER_BTN=0 - -D SX126X_DIO2_AS_RF_SWITCH=true - -D SX126X_DIO3_TCXO_VOLTAGE=1.8 - -D SX126X_CURRENT_LIMIT=130.0f ; for best TX power! - -D SX126X_RX_BOOSTED_GAIN=1 -build_src_filter = ${esp32_base.build_src_filter} -lib_deps = - ${esp32_base.lib_deps} - adafruit/Adafruit SSD1306 @ ^2.5.13 - -[env:Heltec_v3_repeater] -extends = Heltec_lora32_v3 -build_flags = - ${Heltec_lora32_v3.build_flags} - -D DISPLAY_CLASS=SSD1306Display - -D ADVERT_NAME='"Heltec Repeater"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' - -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Heltec_lora32_v3.build_src_filter} - + - +<../examples/simple_repeater> - -[env:Heltec_v3_room_server] -extends = Heltec_lora32_v3 -build_flags = - ${Heltec_lora32_v3.build_flags} - -D DISPLAY_CLASS=SSD1306Display - -D ADVERT_NAME='"Heltec Room"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' - -D ROOM_PASSWORD='"hello"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Heltec_lora32_v3.build_src_filter} - + - +<../examples/simple_room_server> - -[env:Heltec_v3_terminal_chat] -extends = Heltec_lora32_v3 -build_flags = - ${Heltec_lora32_v3.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Heltec_lora32_v3.build_src_filter} - +<../examples/simple_secure_chat/main.cpp> -lib_deps = - ${Heltec_lora32_v3.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[env:Heltec_v3_companion_radio_usb] -extends = Heltec_lora32_v3 -build_flags = - ${Heltec_lora32_v3.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 - -D DISPLAY_CLASS=SSD1306Display -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 -; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 -build_src_filter = ${Heltec_lora32_v3.build_src_filter} - + - +<../examples/companion_radio> -lib_deps = - ${Heltec_lora32_v3.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[env:Heltec_v3_companion_radio_ble] -extends = Heltec_lora32_v3 -build_flags = - ${Heltec_lora32_v3.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 - -D DISPLAY_CLASS=SSD1306Display - -D BLE_PIN_CODE=0 ; dynamic, random PIN - -D BLE_DEBUG_LOGGING=1 -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Heltec_lora32_v3.build_src_filter} - + - + - +<../examples/companion_radio> -lib_deps = - ${Heltec_lora32_v3.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[env:Heltec_v3_companion_radio_wifi] -extends = Heltec_lora32_v3 -build_flags = - ${Heltec_lora32_v3.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 - -D DISPLAY_CLASS=SSD1306Display - -D WIFI_DEBUG_LOGGING=1 - -D WIFI_SSID='"myssid"' - -D WIFI_PWD='"mypwd"' -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Heltec_lora32_v3.build_src_filter} - + - + - +<../examples/companion_radio> -lib_deps = - ${Heltec_lora32_v3.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[env:Heltec_WSL3_repeater] -extends = Heltec_lora32_v3 -build_flags = - ${Heltec_lora32_v3.build_flags} - -D ADVERT_NAME='"Heltec Repeater"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' - -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Heltec_lora32_v3.build_src_filter} - +<../examples/simple_repeater> - -[env:Heltec_WSL3_room_server] -extends = Heltec_lora32_v3 -build_src_filter = ${Heltec_lora32_v3.build_src_filter} - +<../examples/simple_room_server> -build_flags = - ${Heltec_lora32_v3.build_flags} - -D ADVERT_NAME='"Heltec Room"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' - -D ROOM_PASSWORD='"hello"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 - -[env:Heltec_WSL3_companion_radio_ble] -extends = Heltec_lora32_v3 -build_flags = - ${Heltec_lora32_v3.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 - -D BLE_PIN_CODE=123456 - -D BLE_DEBUG_LOGGING=1 -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Heltec_lora32_v3.build_src_filter} - + - +<../examples/companion_radio> -lib_deps = - ${Heltec_lora32_v3.lib_deps} - densaugeo/base64 @ ~1.4.0 - -; ================ -[Xiao_esp32_C3] -extends = esp32_base -board = seeed_xiao_esp32c3 -build_flags = - ${esp32_base.build_flags} - -D LORA_TX_BOOST_PIN=D3 - -D P_LORA_TX_LED=D5 - -D PIN_VBAT_READ=D0 - -D P_LORA_DIO_1=D2 - -D P_LORA_NSS=D4 - -D P_LORA_RESET=RADIOLIB_NC - -D P_LORA_BUSY=D1 - -D PIN_BOARD_SDA=D6 - -D PIN_BOARD_SCL=D7 - -D SX126X_DIO2_AS_RF_SWITCH=true - -D SX126X_DIO3_TCXO_VOLTAGE=1.8 - -D SX126X_CURRENT_LIMIT=130.0f ; for best TX power! - -[env:Xiao_C3_Repeater_sx1262] -extends = Xiao_esp32_C3 -build_src_filter = ${Xiao_esp32_C3.build_src_filter} - +<../examples/simple_repeater/main.cpp> -build_flags = - ${Xiao_esp32_C3.build_flags} - -D RADIO_CLASS=CustomSX1262 - -D WRAPPER_CLASS=CustomSX1262Wrapper - -D SX126X_RX_BOOSTED_GAIN=1 - -D LORA_TX_POWER=22 - -D ADVERT_NAME='"Xiao Repeater"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 - -[env:Xiao_C3_Repeater_sx1268] -extends = Xiao_esp32_C3 -build_src_filter = ${Xiao_esp32_C3.build_src_filter} - +<../examples/simple_repeater/main.cpp> -build_flags = - ${Xiao_esp32_C3.build_flags} - -D RADIO_CLASS=CustomSX1268 - -D WRAPPER_CLASS=CustomSX1268Wrapper - -D LORA_TX_POWER=22 - -D ADVERT_NAME='"Xiao Repeater"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' - ; -D MESH_PACKET_LOGGING=1 - ; -D MESH_DEBUG=1 - -; ============= -[Xiao_S3_WIO] -extends = esp32_base -board = seeed_xiao_esp32s3 -board_check = true -board_build.mcu = esp32s3 -build_flags = ${esp32_base.build_flags} - -D SEEED_XIAO_S3 - -D P_LORA_DIO_1=39 - -D P_LORA_NSS=41 - -D P_LORA_RESET=42 ; RADIOLIB_NC - -D P_LORA_BUSY=40 ; DIO2 = 38 - -D P_LORA_SCLK=7 - -D P_LORA_MISO=8 - -D P_LORA_MOSI=9 - -D SX126X_DIO2_AS_RF_SWITCH=true - -D SX126X_DIO3_TCXO_VOLTAGE=1.8 - -D SX126X_CURRENT_LIMIT=130 - -D RADIO_CLASS=CustomSX1262 - -D WRAPPER_CLASS=CustomSX1262Wrapper - -D LORA_TX_POWER=22 - -D SX126X_RX_BOOSTED_GAIN=1 - -[env:Xiao_S3_WIO_Repeater] -extends = Xiao_S3_WIO -build_src_filter = ${Xiao_S3_WIO.build_src_filter} - +<../examples/simple_repeater/main.cpp> -build_flags = - ${Xiao_S3_WIO.build_flags} - -D ADVERT_NAME='"XiaoS3 Repeater"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 - -[env:Xiao_S3_WIO_terminal_chat] -extends = Xiao_S3_WIO -build_flags = - ${Xiao_S3_WIO.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Xiao_S3_WIO.build_src_filter} - +<../examples/simple_secure_chat/main.cpp> -lib_deps = - ${Xiao_S3_WIO.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[env:Xiao_S3_WIO_companion_radio_ble] -extends = Xiao_S3_WIO -build_flags = - ${Xiao_S3_WIO.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 - -D BLE_PIN_CODE=123456 -; -D BLE_DEBUG_LOGGING=1 -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Xiao_S3_WIO.build_src_filter} - + - +<../examples/companion_radio/main.cpp> -lib_deps = - ${Xiao_S3_WIO.lib_deps} - densaugeo/base64 @ ~1.4.0 - -; ============= -[LilyGo_TLora_V2_1_1_6] -extends = esp32_base -board = ttgo-lora32-v1 ; LILYGO T-LoRa V2.1-1.6 ESP32 with SX1276 -build_unflags = -Os -build_type = release ; Set build type to release -board_build.partitions = min_spiffs.csv ; get around 4mb flash limit -build_flags = - ${esp32_base.build_flags} - -Os -ffunction-sections -fdata-sections ; Optimize for size - -D LILYGO_TLORA ; LILYGO T-LoRa V2.1-1.6 ESP32 with SX1276 - -D P_LORA_DIO_0=26 ; SX1276 DIO0 interrupt pin - -D P_LORA_DIO_1=33 ; SX1276 DIO1 interrupt pin - -D P_LORA_NSS=18 ; Chip select - SS pin - -D P_LORA_RESET=14 ; Reset pin - -D P_LORA_SCLK=5 ; SPI clock - -D P_LORA_MISO=19 ; SPI MISO - -D P_LORA_MOSI=27 ; SPI MOSI - -D P_LORA_TX_LED=2 ; LED pin for TX indication - -D PIN_VBAT_READ=35 ; Battery voltage reading (analog pin) - -D PIN_USER_BTN=0 - -D RADIO_CLASS=CustomSX1276 - -D ARDUINO_LOOP_STACK_SIZE=16384 - -D DISPLAY_CLASS=SSD1306Display - -D WRAPPER_CLASS=CustomSX1276Wrapper - -D LORA_TX_POWER=20 -lib_deps = - ${esp32_base.lib_deps} - adafruit/Adafruit SSD1306 @ ^2.5.13 - -; === LILYGO T-LoRa V2.1-1.6 with SX1276 environments === -[env:LilyGo_TLora_V2_1_1_6_Repeater] -extends = LilyGo_TLora_V2_1_1_6 -build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} - + - +<../examples/simple_repeater> -build_flags = - ${LilyGo_TLora_V2_1_1_6.build_flags} - -D ADVERT_NAME='"TLora-V2.1-1.6 Repeater"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -; -D CORE_DEBUG_LEVEL=3 - -[env:LilyGo_TLora_V2_1_1_6_terminal_chat] -extends = LilyGo_TLora_V2_1_1_6 -build_flags = - ${LilyGo_TLora_V2_1_1_6.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} - + - +<../examples/simple_repeater> -lib_deps = - ${LilyGo_TLora_V2_1_1_6.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[env:LilyGo_TLora_V2_1_1_6_companion_radio_usb] -extends = LilyGo_TLora_V2_1_1_6 -build_flags = - ${LilyGo_TLora_V2_1_1_6.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 -; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 -build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} - + - +<../examples/companion_radio> -lib_deps = - ${LilyGo_TLora_V2_1_1_6.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[env:LilyGo_TLora_V2_1_1_6_companion_radio_ble] -extends = LilyGo_TLora_V2_1_1_6 -build_flags = - ${LilyGo_TLora_V2_1_1_6.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 - -D BLE_PIN_CODE=123456 -; -D BLE_DEBUG_LOGGING=1 -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} - + - + - +<../examples/companion_radio> -lib_deps = - ${LilyGo_TLora_V2_1_1_6.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[env:LilyGo_TLora_V2_1_1_6_room_server] -extends = LilyGo_TLora_V2_1_1_6 -build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} - + - +<../examples/simple_room_server> -build_flags = - ${LilyGo_TLora_V2_1_1_6.build_flags} - -D ADVERT_NAME='"TLora-V2.1-1.6 Room"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' - -D ROOM_PASSWORD='"hello"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 - -; ============= -[LilyGo_T3S3_sx1262] -extends = esp32_base -board = t3_s3_v1_x -build_flags = - ${esp32_base.build_flags} - -D LILYGO_T3S3 - -D P_LORA_DIO_1=33 - -D P_LORA_NSS=7 - -D P_LORA_RESET=8 ; RADIOLIB_NC - -D P_LORA_BUSY=34 - -D P_LORA_SCLK=5 - -D P_LORA_MISO=3 - -D P_LORA_MOSI=6 - -D P_LORA_TX_LED=37 - -D PIN_VBAT_READ=1 - -D PIN_USER_BTN=0 - -D PIN_BOARD_SDA=18 - -D PIN_BOARD_SCL=17 - -D P_LORA_TX_LED=37 - -D PIN_OLED_RESET=21 - -D SX126X_DIO2_AS_RF_SWITCH=true - -D SX126X_DIO3_TCXO_VOLTAGE=1.8 - -D SX126X_CURRENT_LIMIT=130 - -D RADIO_CLASS=CustomSX1262 - -D WRAPPER_CLASS=CustomSX1262Wrapper - -D LORA_TX_POWER=22 - -D SX126X_RX_BOOSTED_GAIN=1 -build_src_filter = ${esp32_base.build_src_filter} -lib_deps = - ${esp32_base.lib_deps} - adafruit/Adafruit SSD1306 @ ^2.5.13 - -; === LilyGo T3S3 with SX1262 environments === -[env:LilyGo_T3S3_sx1262_Repeater] -extends = LilyGo_T3S3_sx1262 -build_flags = - ${LilyGo_T3S3_sx1262.build_flags} - -D DISPLAY_CLASS=SSD1306Display - -D ADVERT_NAME='"T3S3-1262 Repeater"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} - + - +<../examples/simple_repeater> - -[env:LilyGo_T3S3_sx1262_terminal_chat] -extends = LilyGo_T3S3_sx1262 -build_flags = - ${LilyGo_T3S3_sx1262.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} - +<../examples/simple_secure_chat/main.cpp> -lib_deps = - ${LilyGo_T3S3_sx1262.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[env:LilyGo_T3S3_sx1262_room_server] -extends = LilyGo_T3S3_sx1262 -build_flags = - ${LilyGo_T3S3_sx1262.build_flags} - -D DISPLAY_CLASS=SSD1306Display - -D ADVERT_NAME='"T3S3-1262 Room"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' - -D ROOM_PASSWORD='"hello"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} - + - +<../examples/simple_room_server> - -[env:LilyGo_T3S3_sx1262_companion_radio_usb] -extends = LilyGo_T3S3_sx1262 -build_flags = - ${LilyGo_T3S3_sx1262.build_flags} - -D DISPLAY_CLASS=SSD1306Display - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 -; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 -build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} - + - +<../examples/companion_radio> -lib_deps = - ${LilyGo_T3S3_sx1262.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[env:LilyGo_T3S3_sx1262_companion_radio_ble] -extends = LilyGo_T3S3_sx1262 -build_flags = - ${LilyGo_T3S3_sx1262.build_flags} - -D DISPLAY_CLASS=SSD1306Display - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 - -D BLE_PIN_CODE=123456 - -D BLE_DEBUG_LOGGING=1 -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} - + - + - +<../examples/companion_radio> -lib_deps = - ${LilyGo_T3S3_sx1262.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[Station_G2] -extends = esp32_base -board = station-g2 -build_flags = - ${esp32_base.build_flags} - -D STATION_G2 - -D RADIO_CLASS=CustomSX1262 - -D WRAPPER_CLASS=CustomSX1262Wrapper - -D LORA_TX_POWER=7 -; -D P_LORA_TX_LED=35 -; -D PIN_BOARD_SDA=5 -; -D PIN_BOARD_SCL=6 - -D PIN_USER_BTN=0 - -D SX126X_DIO2_AS_RF_SWITCH=true - -D SX126X_DIO3_TCXO_VOLTAGE=1.8 - -D SX126X_CURRENT_LIMIT=130.0f ; for best TX power! -; -D SX126X_RX_BOOSTED_GAIN=1 - DO NOT ENABLE THIS! -; https://wiki.uniteng.com/en/meshtastic/station-g2#impact-of-lora-node-dense-areashigh-noise-environments-on-rf-performance - -build_src_filter = ${esp32_base.build_src_filter} -lib_deps = - ${esp32_base.lib_deps} - -[env:Station_G2_repeater] -extends = Station_G2 -build_flags = - ${Station_G2.build_flags} - -D ADVERT_NAME='"Station G2 Repeater"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' - -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Station_G2.build_src_filter} - +<../examples/simple_repeater> - -[env:Station_G2_room_server] -extends = Station_G2 -build_src_filter = ${Station_G2.build_src_filter} - +<../examples/simple_room_server> -build_flags = - ${Station_G2.build_flags} - -D ADVERT_NAME='"Station G2 Room"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' - -D ROOM_PASSWORD='"hello"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 - -[LilyGo_TBeam] -extends = esp32_base -board = ttgo-t-beam -build_flags = - ${esp32_base.build_flags} - -D LILYGO_TBEAM - -D RADIO_CLASS=CustomSX1276 - -D WRAPPER_CLASS=CustomSX1276Wrapper - -D LORA_TX_POWER=20 - -D P_LORA_TX_LED=4 -build_src_filter = ${esp32_base.build_src_filter} -board_build.partitions = min_spiffs.csv ; get around 4mb flash limit - -[env:Tbeam_companion_radio_ble] -extends = LilyGo_TBeam -board_build.upload.maximum_ram_size=2000000 -build_flags = - ${LilyGo_TBeam.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 - -D BLE_PIN_CODE=123456 - -D BLE_DEBUG_LOGGING=1 - -D MESH_PACKET_LOGGING=1 - -D MESH_DEBUG=1 - -D RADIOLIB_DEBUG_BASIC=1 -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${LilyGo_TBeam.build_src_filter} - + - +<../examples/companion_radio/main.cpp> -lib_deps = - ${LilyGo_TBeam.lib_deps} - densaugeo/base64 @ ~1.4.0 - lewisxhe/XPowersLib@^0.2.7 - ; ----------------- NRF52 --------------------- [nrf52_base] @@ -767,483 +56,3 @@ lib_deps = ${nrf52_base.lib_deps} rweather/Crypto @ ^0.4.0 https://github.com/adafruit/Adafruit_nRF52_Arduino - -[rak4631] -extends = nrf52840_base -platform = https://github.com/maxgerhardt/platform-nordicnrf52.git#rak -board = wiscore_rak4631 -board_check = true -build_flags = ${nrf52840_base.build_flags} - -D RAK_4631 - -D PIN_USER_BTN=9 - -D RADIO_CLASS=CustomSX1262 - -D WRAPPER_CLASS=CustomSX1262Wrapper - -D LORA_TX_POWER=22 - -D SX126X_CURRENT_LIMIT=130 - -D SX126X_RX_BOOSTED_GAIN=1 -build_src_filter = ${nrf52840_base.build_src_filter} - + -lib_deps = - ${nrf52840_base.lib_deps} - adafruit/Adafruit SSD1306 @ ^2.5.13 - -[env:RAK_4631_Repeater] -extends = rak4631 -build_flags = - ${rak4631.build_flags} - -D DISPLAY_CLASS=SSD1306Display - -D ADVERT_NAME='"RAK4631 Repeater"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${rak4631.build_src_filter} - + - +<../examples/simple_repeater> - -[env:RAK_4631_room_server] -extends = rak4631 -build_flags = - ${rak4631.build_flags} - -D DISPLAY_CLASS=SSD1306Display - -D ADVERT_NAME='"Test Room"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' - -D ROOM_PASSWORD='"hello"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${rak4631.build_src_filter} - + - +<../examples/simple_room_server> - -[env:RAK_4631_companion_radio_usb] -extends = rak4631 -build_flags = - ${rak4631.build_flags} - -D DISPLAY_CLASS=SSD1306Display - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 -; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 -build_src_filter = ${rak4631.build_src_filter} - + - +<../examples/companion_radio> -lib_deps = - ${rak4631.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[env:RAK_4631_companion_radio_ble] -extends = rak4631 -build_flags = - ${rak4631.build_flags} - -D DISPLAY_CLASS=SSD1306Display - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 - -D BLE_PIN_CODE=123456 - -D BLE_DEBUG_LOGGING=1 -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${rak4631.build_src_filter} - + - + - +<../examples/companion_radio> -lib_deps = - ${rak4631.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[env:RAK_4631_terminal_chat] -extends = rak4631 -build_flags = - ${rak4631.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 - -D MESH_PACKET_LOGGING=1 - -D MESH_DEBUG=1 -build_src_filter = ${rak4631.build_src_filter} - +<../examples/simple_secure_chat/main.cpp> -lib_deps = - ${rak4631.lib_deps} - densaugeo/base64 @ ~1.4.0 - -; ----------------- NRF52 T1000e--------------------- -[nrf52840_t1000e] -extends = nrf52_base -platform_packages = framework-arduinoadafruitnrf52 -build_flags = ${nrf52_base.build_flags} - -I src/helpers/nrf52 - -I lib/nrf52/s140_nrf52_7.3.0_API/include - -I lib/nrf52/s140_nrf52_7.3.0_API/include/nrf52 -lib_ignore = - BluetoothOTA - lvgl - lib5b4 -lib_deps = - ${nrf52_base.lib_deps} - rweather/Crypto @ ^0.4.0 - -[t1000-e] -extends = nrf52840_t1000e -board = tracker-t1000-e -board_build.ldscript = boards/nrf52840_s140_v7.ld -build_flags = ${nrf52840_t1000e.build_flags} - -Ivariants/t1000-e - -D T1000_E - -D PIN_USER_BTN=6 - -D USER_BTN_PRESSED=HIGH - -D PIN_STATUS_LED=24 - -D RADIO_CLASS=CustomLR1110 - -D WRAPPER_CLASS=CustomLR1110Wrapper - -D MAX_LORA_TX_POWER=22 -build_src_filter = ${nrf52840_t1000e.build_src_filter} - + - + - +<../variants/t1000-e> -debug_tool = jlink -upload_protocol = nrfutil - -[env:t1000e_companion_radio_ble] -extends = t1000-e -build_flags = ${t1000-e.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 - -D BLE_PIN_CODE=123456 - -D BLE_DEBUG_LOGGING=1 - -D MESH_PACKET_LOGGING=1 - -D MESH_DEBUG=1 - -D HAS_UI -build_src_filter = ${t1000-e.build_src_filter} - + - +<../examples/companion_radio/*.cpp> -lib_deps = ${t1000-e.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[nrf52840_t114] -extends = nrf52_base -platform_packages = framework-arduinoadafruitnrf52 -build_flags = ${nrf52_base.build_flags} - -I src/helpers/nrf52 - -I lib/nrf52/s140_nrf52_6.1.1_API/include - -I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52 -lib_deps = - ${nrf52_base.lib_deps} - rweather/Crypto @ ^0.4.0 - -[Heltec_t114] -extends = nrf52840_t114 -board = heltec_t114 -board_build.ldscript = boards/nrf52840_s140_v6.ld -build_flags = ${nrf52840_t114.build_flags} - -Ivariants/t114 - -DHELTEC_T114 - -D P_LORA_TX_LED=35 - -D RADIO_CLASS=CustomSX1262 - -D WRAPPER_CLASS=CustomSX1262Wrapper - -D LORA_TX_POWER=22 - -D SX126X_CURRENT_LIMIT=130 - -D SX126X_RX_BOOSTED_GAIN=1 -build_src_filter = ${nrf52840_t114.build_src_filter} - + - + - +<../variants/t114> -debug_tool = jlink -upload_protocol = nrfutil - -[env:Heltec_t114_repeater] -extends = Heltec_t114 -build_src_filter = ${Heltec_t114.build_src_filter} - +<../examples/simple_repeater/main.cpp> -build_flags = - ${Heltec_t114.build_flags} - -D ADVERT_NAME='"Heltec_T114 Repeater"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 - -[env:Heltec_t114_room_server] -extends = Heltec_t114 -build_src_filter = ${Heltec_t114.build_src_filter} - +<../examples/simple_room_server> -build_flags = - ${Heltec_t114.build_flags} - -D ADVERT_NAME='"Heltec_T114 Room"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' - -D ROOM_PASSWORD='"hello"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 - -[env:Heltec_t114_companion_radio_ble] -extends = Heltec_t114 -build_flags = - ${Heltec_t114.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 - -D BLE_PIN_CODE=123456 - -D BLE_DEBUG_LOGGING=1 -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${Heltec_t114.build_src_filter} - + - +<../examples/companion_radio/main.cpp> -lib_deps = - ${Heltec_t114.lib_deps} - densaugeo/base64 @ ~1.4.0 - -[nrf52840_techo] -extends = nrf52_base -platform_packages = framework-arduinoadafruitnrf52 -build_flags = ${nrf52_base.build_flags} - -I src/helpers/nrf52 - -I lib/nrf52/s140_nrf52_6.1.1_API/include - -I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52 -lib_deps = - ${nrf52_base.lib_deps} - rweather/Crypto @ ^0.4.0 - -[LilyGo_Techo] -extends = nrf52840_techo -board = t-echo -board_build.ldscript = boards/nrf52840_s140_v6.ld -build_flags = ${nrf52840_techo.build_flags} - -Ivariants/techo - -DLILYGO_TECHO - -D RADIO_CLASS=CustomSX1262 - -D WRAPPER_CLASS=CustomSX1262Wrapper - -D LORA_TX_POWER=22 - -D SX126X_CURRENT_LIMIT=130 - -D SX126X_RX_BOOSTED_GAIN=1 -build_src_filter = ${nrf52840_techo.build_src_filter} - + - + - +<../variants/techo> -debug_tool = jlink -upload_protocol = nrfutil - -[env:LilyGo_T-Echo_repeater] -extends = LilyGo_Techo -build_src_filter = ${LilyGo_Techo.build_src_filter} +<../examples/simple_repeater/main.cpp> -build_flags = - ${LilyGo_Techo.build_flags} - -D ADVERT_NAME='"T-Echo Repeater"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 - -[env:LilyGo_T-Echo_room_server] -extends = LilyGo_Techo -build_src_filter = ${LilyGo_Techo.build_src_filter} +<../examples/simple_room_server/main.cpp> -build_flags = - ${LilyGo_Techo.build_flags} - -D ADVERT_NAME='"T-Echo Room"' - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD='"password"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 - -[env:LilyGo_T-Echo_companion_radio_ble] -extends = LilyGo_Techo -build_flags = - ${LilyGo_Techo.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 - -D BLE_PIN_CODE=123456 - -D BLE_DEBUG_LOGGING=1 -; -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D ENABLE_PRIVATE_KEY_EXPORT=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${LilyGo_Techo.build_src_filter} - + - +<../examples/companion_radio/main.cpp> -lib_deps = - ${LilyGo_Techo.lib_deps} - densaugeo/base64 @ ~1.4.0 - - -[faketec] -extends = nrf52840_base -board = promicro_nrf52840 -build_src_filter = ${nrf52840_base.build_src_filter} + -build_flags = ${nrf52840_base.build_flags} - -D FAKETEC - -D RADIO_CLASS=CustomSX1262 - -D WRAPPER_CLASS=CustomSX1262Wrapper - -D LORA_TX_POWER=22 - -D SX126X_CURRENT_LIMIT=130 - -D SX126X_RX_BOOSTED_GAIN=1 - -[env:Faketec_Repeater] -extends = faketec -build_src_filter = ${faketec.build_src_filter} +<../examples/simple_repeater/main.cpp> -build_flags = - ${faketec.build_flags} - -D ADVERT_NAME="\"Faketec Repeater\"" - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -lib_deps = - ${faketec.lib_deps} - adafruit/RTClib @ ^2.1.3 - -[env:Faketec_room_server] -extends = faketec -build_src_filter = ${faketec.build_src_filter} +<../examples/simple_room_server/main.cpp> -build_flags = - ${faketec.build_flags} - -D ADVERT_NAME="\"Test Room\"" - -D ADVERT_LAT=-37.0 - -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" - -D ROOM_PASSWORD="\"hello\"" -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -lib_deps = - ${faketec.lib_deps} - adafruit/RTClib @ ^2.1.3 - -[env:Faketec_terminal_chat] -extends = faketec -build_flags = - ${faketec.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${faketec.build_src_filter} +<../examples/simple_secure_chat/main.cpp> -lib_deps = - ${faketec.lib_deps} - densaugeo/base64 @ ~1.4.0 - adafruit/RTClib @ ^2.1.3 - -[env:Faketec_companion_radio_usb] -extends = faketec -build_flags = - ${faketec.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 -; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 -; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 -build_src_filter = ${faketec.build_src_filter} +<../examples/companion_radio/main.cpp> -lib_deps = - ${faketec.lib_deps} - adafruit/RTClib @ ^2.1.3 - densaugeo/base64 @ ~1.4.0 - -[env:Faketec_companion_radio_ble] -extends = faketec -build_flags = - ${faketec.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 - -D BLE_PIN_CODE=123456 - -D BLE_DEBUG_LOGGING=1 - -D ENABLE_PRIVATE_KEY_EXPORT=1 - -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${faketec.build_src_filter} + +<../examples/companion_radio/main.cpp> -lib_deps = - ${faketec.lib_deps} - adafruit/RTClib @ ^2.1.3 - densaugeo/base64 @ ~1.4.0 - -[ProMicroLLCC68] -extends = nrf52840_base -board = promicro_nrf52840 -build_src_filter = ${nrf52840_base.build_src_filter} + -build_flags = ${nrf52840_base.build_flags} - -D FAKETEC - -D RADIO_CLASS=CustomLLCC68 - -D WRAPPER_CLASS=CustomLLCC68Wrapper - -D LORA_TX_POWER=22 - -D SX126X_CURRENT_LIMIT=130 - -D SX126X_RX_BOOSTED_GAIN=1 - -[env:ProMicroLLCC68_Repeater] -extends = ProMicroLLCC68 -build_src_filter = ${ProMicroLLCC68.build_src_filter} +<../examples/simple_repeater/main.cpp> -build_flags = - ${ProMicroLLCC68.build_flags} - -D ADVERT_NAME="\"ProMicroLLCC68 Repeater\"" - -D ADMIN_PASSWORD="\"password\"" -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -lib_deps = - ${ProMicroLLCC68.lib_deps} - adafruit/RTClib @ ^2.1.3 - -[env:ProMicroLLCC68_room_server] -extends = ProMicroLLCC68 -build_src_filter = ${ProMicroLLCC68.build_src_filter} +<../examples/simple_room_server/main.cpp> -build_flags = - ${ProMicroLLCC68.build_flags} - -D ADVERT_NAME="\"ProMicroLLCC68 Room\"" - -D ADMIN_PASSWORD="\"password\"" - -D ROOM_PASSWORD="\"hello\"" -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -lib_deps = - ${ProMicroLLCC68.lib_deps} - adafruit/RTClib @ ^2.1.3 - -[env:ProMicroLLCC68_terminal_chat] -extends = ProMicroLLCC68 -build_flags = - ${ProMicroLLCC68.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${ProMicroLLCC68.build_src_filter} +<../examples/simple_secure_chat/main.cpp> -lib_deps = - ${ProMicroLLCC68.lib_deps} - densaugeo/base64 @ ~1.4.0 - adafruit/RTClib @ ^2.1.3 - -[env:ProMicroLLCC68_companion_radio_usb] -extends = ProMicroLLCC68 -build_flags = - ${ProMicroLLCC68.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 -; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 -; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 -build_src_filter = ${ProMicroLLCC68.build_src_filter} +<../examples/companion_radio/main.cpp> -lib_deps = - ${ProMicroLLCC68.lib_deps} - adafruit/RTClib @ ^2.1.3 - densaugeo/base64 @ ~1.4.0 - -[env:ProMicroLLCC68_companion_radio_ble] -extends = ProMicroLLCC68 -build_flags = - ${ProMicroLLCC68.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 - -D BLE_PIN_CODE=123456 - -D BLE_DEBUG_LOGGING=1 - -D ENABLE_PRIVATE_KEY_EXPORT=1 - -D ENABLE_PRIVATE_KEY_IMPORT=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 -build_src_filter = ${ProMicroLLCC68.build_src_filter} + +<../examples/companion_radio/main.cpp> -lib_deps = - ${ProMicroLLCC68.lib_deps} - adafruit/RTClib @ ^2.1.3 - densaugeo/base64 @ ~1.4.0 \ No newline at end of file diff --git a/variants/heltec_v2/platformio.ini b/variants/heltec_v2/platformio.ini new file mode 100644 index 00000000..99638c2b --- /dev/null +++ b/variants/heltec_v2/platformio.ini @@ -0,0 +1,101 @@ +[Heltec_lora32_v2] +extends = esp32_base +board = heltec_wifi_lora_32_V2 ; heltec_wifi_lora_32_V2 +build_flags = + ${esp32_base.build_flags} + -D HELTEC_LORA_V2 + -D PIN_BOARD_SDA=4 + -D PIN_BOARD_SCL=15 + -D PIN_USER_BTN=0 + -D PIN_OLED_RESET=16 + -D RADIO_CLASS=CustomSX1276 + -D WRAPPER_CLASS=CustomSX1276Wrapper + -D LORA_TX_POWER=20 + -D P_LORA_TX_LED=25 +build_src_filter = ${esp32_base.build_src_filter} +lib_deps = + ${esp32_base.lib_deps} + adafruit/Adafruit SSD1306 @ ^2.5.13 + +[env:Heltec_v2_repeater] +extends = Heltec_lora32_v2 +build_flags = + ${Heltec_lora32_v2.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"Heltec Repeater"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v2.build_src_filter} + +<../examples/simple_repeater> + + + +[env:Heltec_v2_room_server] +extends = Heltec_lora32_v2 +build_flags = + ${Heltec_lora32_v2.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"Heltec Room"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v2.build_src_filter} + + + +<../examples/simple_room_server> + +[env:Heltec_v2_terminal_chat] +extends = Heltec_lora32_v2 +build_flags = + ${Heltec_lora32_v2.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v2.build_src_filter} + +<../examples/simple_secure_chat/main.cpp> +lib_deps = + ${Heltec_lora32_v2.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:Heltec_v2_companion_radio_usb] +extends = Heltec_lora32_v2 +build_flags = + ${Heltec_lora32_v2.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 +; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 +; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v2.build_src_filter} + + + + + +<../examples/companion_radio> +lib_deps = + ${Heltec_lora32_v2.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:Heltec_v2_companion_radio_ble] +extends = Heltec_lora32_v2 +build_flags = + ${Heltec_lora32_v2.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=0 + -D BLE_DEBUG_LOGGING=1 +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v2.build_src_filter} + + + + + +<../examples/companion_radio> +lib_deps = + ${Heltec_lora32_v2.lib_deps} + densaugeo/base64 @ ~1.4.0 diff --git a/variants/heltec_v3/platformio.ini b/variants/heltec_v3/platformio.ini new file mode 100644 index 00000000..f32a12c4 --- /dev/null +++ b/variants/heltec_v3/platformio.ini @@ -0,0 +1,173 @@ +[Heltec_lora32_v3] +extends = esp32_base +board = esp32-s3-devkitc-1 +build_flags = + ${esp32_base.build_flags} + -D HELTEC_LORA_V3 + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D P_LORA_TX_LED=35 + -D PIN_BOARD_SDA=17 + -D PIN_BOARD_SCL=18 + -D PIN_USER_BTN=0 + -D SX126X_DIO2_AS_RF_SWITCH=true + -D SX126X_DIO3_TCXO_VOLTAGE=1.8 + -D SX126X_CURRENT_LIMIT=130.0f ; for best TX power! + -D SX126X_RX_BOOSTED_GAIN=1 +build_src_filter = ${esp32_base.build_src_filter} +lib_deps = + ${esp32_base.lib_deps} + adafruit/Adafruit SSD1306 @ ^2.5.13 + +[env:Heltec_v3_repeater] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"Heltec Repeater"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' + -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + +<../examples/simple_repeater> + +[env:Heltec_v3_room_server] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"Heltec Room"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + +<../examples/simple_room_server> + +[env:Heltec_v3_terminal_chat] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + +<../examples/simple_secure_chat/main.cpp> +lib_deps = + ${Heltec_lora32_v3.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:Heltec_v3_companion_radio_usb] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D DISPLAY_CLASS=SSD1306Display +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 +; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + +<../examples/companion_radio> +lib_deps = + ${Heltec_lora32_v3.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:Heltec_v3_companion_radio_ble] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D DISPLAY_CLASS=SSD1306Display + -D BLE_PIN_CODE=0 ; dynamic, random PIN + -D BLE_DEBUG_LOGGING=1 +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + + + +<../examples/companion_radio> +lib_deps = + ${Heltec_lora32_v3.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:Heltec_v3_companion_radio_wifi] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D DISPLAY_CLASS=SSD1306Display + -D WIFI_DEBUG_LOGGING=1 + -D WIFI_SSID='"myssid"' + -D WIFI_PWD='"mypwd"' +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + + + +<../examples/companion_radio> +lib_deps = + ${Heltec_lora32_v3.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:Heltec_WSL3_repeater] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D ADVERT_NAME='"Heltec Repeater"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' + -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + +<../examples/simple_repeater> + +[env:Heltec_WSL3_room_server] +extends = Heltec_lora32_v3 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + +<../examples/simple_room_server> +build_flags = + ${Heltec_lora32_v3.build_flags} + -D ADVERT_NAME='"Heltec Room"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 + +[env:Heltec_WSL3_companion_radio_ble] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + +<../examples/companion_radio> +lib_deps = + ${Heltec_lora32_v3.lib_deps} + densaugeo/base64 @ ~1.4.0 diff --git a/variants/lilygo_t3s3/platformio.ini b/variants/lilygo_t3s3/platformio.ini new file mode 100644 index 00000000..f86657f5 --- /dev/null +++ b/variants/lilygo_t3s3/platformio.ini @@ -0,0 +1,116 @@ +[LilyGo_T3S3_sx1262] +extends = esp32_base +board = t3_s3_v1_x +build_flags = + ${esp32_base.build_flags} + -D LILYGO_T3S3 + -D P_LORA_DIO_1=33 + -D P_LORA_NSS=7 + -D P_LORA_RESET=8 ; RADIOLIB_NC + -D P_LORA_BUSY=34 + -D P_LORA_SCLK=5 + -D P_LORA_MISO=3 + -D P_LORA_MOSI=6 + -D P_LORA_TX_LED=37 + -D PIN_VBAT_READ=1 + -D PIN_USER_BTN=0 + -D PIN_BOARD_SDA=18 + -D PIN_BOARD_SCL=17 + -D P_LORA_TX_LED=37 + -D PIN_OLED_RESET=21 + -D SX126X_DIO2_AS_RF_SWITCH=true + -D SX126X_DIO3_TCXO_VOLTAGE=1.8 + -D SX126X_CURRENT_LIMIT=130 + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D SX126X_RX_BOOSTED_GAIN=1 +build_src_filter = ${esp32_base.build_src_filter} +lib_deps = + ${esp32_base.lib_deps} + adafruit/Adafruit SSD1306 @ ^2.5.13 + +; === LilyGo T3S3 with SX1262 environments === +[env:LilyGo_T3S3_sx1262_Repeater] +extends = LilyGo_T3S3_sx1262 +build_flags = + ${LilyGo_T3S3_sx1262.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"T3S3-1262 Repeater"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} + + + +<../examples/simple_repeater> + +[env:LilyGo_T3S3_sx1262_terminal_chat] +extends = LilyGo_T3S3_sx1262 +build_flags = + ${LilyGo_T3S3_sx1262.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} + +<../examples/simple_secure_chat/main.cpp> +lib_deps = + ${LilyGo_T3S3_sx1262.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:LilyGo_T3S3_sx1262_room_server] +extends = LilyGo_T3S3_sx1262 +build_flags = + ${LilyGo_T3S3_sx1262.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"T3S3-1262 Room"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} + + + +<../examples/simple_room_server> + +[env:LilyGo_T3S3_sx1262_companion_radio_usb] +extends = LilyGo_T3S3_sx1262 +build_flags = + ${LilyGo_T3S3_sx1262.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 +; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} + + + +<../examples/companion_radio> +lib_deps = + ${LilyGo_T3S3_sx1262.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:LilyGo_T3S3_sx1262_companion_radio_ble] +extends = LilyGo_T3S3_sx1262 +build_flags = + ${LilyGo_T3S3_sx1262.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} + + + + + +<../examples/companion_radio> +lib_deps = + ${LilyGo_T3S3_sx1262.lib_deps} + densaugeo/base64 @ ~1.4.0 diff --git a/variants/lilygo_tbeam/platformio.ini b/variants/lilygo_tbeam/platformio.ini new file mode 100644 index 00000000..ca233571 --- /dev/null +++ b/variants/lilygo_tbeam/platformio.ini @@ -0,0 +1,36 @@ +[LilyGo_TBeam] +extends = esp32_base +board = ttgo-t-beam +build_flags = + ${esp32_base.build_flags} + -D LILYGO_TBEAM + -D RADIO_CLASS=CustomSX1276 + -D WRAPPER_CLASS=CustomSX1276Wrapper + -D LORA_TX_POWER=20 + -D P_LORA_TX_LED=4 +build_src_filter = ${esp32_base.build_src_filter} +board_build.partitions = min_spiffs.csv ; get around 4mb flash limit + +[env:Tbeam_companion_radio_ble] +extends = LilyGo_TBeam +board_build.upload.maximum_ram_size=2000000 +build_flags = + ${LilyGo_TBeam.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=1 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 + -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 + -D RADIOLIB_DEBUG_BASIC=1 +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_TBeam.build_src_filter} + + + +<../examples/companion_radio/main.cpp> +lib_deps = + ${LilyGo_TBeam.lib_deps} + densaugeo/base64 @ ~1.4.0 + lewisxhe/XPowersLib@^0.2.7 diff --git a/variants/lilygo_tlora_v2_1/platformio.ini b/variants/lilygo_tlora_v2_1/platformio.ini new file mode 100644 index 00000000..0cf3ac92 --- /dev/null +++ b/variants/lilygo_tlora_v2_1/platformio.ini @@ -0,0 +1,111 @@ +[LilyGo_TLora_V2_1_1_6] +extends = esp32_base +board = ttgo-lora32-v1 ; LILYGO T-LoRa V2.1-1.6 ESP32 with SX1276 +build_unflags = -Os +build_type = release ; Set build type to release +board_build.partitions = min_spiffs.csv ; get around 4mb flash limit +build_flags = + ${esp32_base.build_flags} + -Os -ffunction-sections -fdata-sections ; Optimize for size + -D LILYGO_TLORA ; LILYGO T-LoRa V2.1-1.6 ESP32 with SX1276 + -D P_LORA_DIO_0=26 ; SX1276 DIO0 interrupt pin + -D P_LORA_DIO_1=33 ; SX1276 DIO1 interrupt pin + -D P_LORA_NSS=18 ; Chip select - SS pin + -D P_LORA_RESET=14 ; Reset pin + -D P_LORA_SCLK=5 ; SPI clock + -D P_LORA_MISO=19 ; SPI MISO + -D P_LORA_MOSI=27 ; SPI MOSI + -D P_LORA_TX_LED=2 ; LED pin for TX indication + -D PIN_VBAT_READ=35 ; Battery voltage reading (analog pin) + -D PIN_USER_BTN=0 + -D RADIO_CLASS=CustomSX1276 + -D ARDUINO_LOOP_STACK_SIZE=16384 + -D DISPLAY_CLASS=SSD1306Display + -D WRAPPER_CLASS=CustomSX1276Wrapper + -D LORA_TX_POWER=20 +lib_deps = + ${esp32_base.lib_deps} + adafruit/Adafruit SSD1306 @ ^2.5.13 + +; === LILYGO T-LoRa V2.1-1.6 with SX1276 environments === +[env:LilyGo_TLora_V2_1_1_6_Repeater] +extends = LilyGo_TLora_V2_1_1_6 +build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} + + + +<../examples/simple_repeater> +build_flags = + ${LilyGo_TLora_V2_1_1_6.build_flags} + -D ADVERT_NAME='"TLora-V2.1-1.6 Repeater"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +; -D CORE_DEBUG_LEVEL=3 + +[env:LilyGo_TLora_V2_1_1_6_terminal_chat] +extends = LilyGo_TLora_V2_1_1_6 +build_flags = + ${LilyGo_TLora_V2_1_1_6.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${LilyGo_TLora_V2_1_1_6.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:LilyGo_TLora_V2_1_1_6_companion_radio_usb] +extends = LilyGo_TLora_V2_1_1_6 +build_flags = + ${LilyGo_TLora_V2_1_1_6.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 +; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} + + + +<../examples/companion_radio> +lib_deps = + ${LilyGo_TLora_V2_1_1_6.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:LilyGo_TLora_V2_1_1_6_companion_radio_ble] +extends = LilyGo_TLora_V2_1_1_6 +build_flags = + ${LilyGo_TLora_V2_1_1_6.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 +; -D BLE_DEBUG_LOGGING=1 +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} + + + + + +<../examples/companion_radio> +lib_deps = + ${LilyGo_TLora_V2_1_1_6.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:LilyGo_TLora_V2_1_1_6_room_server] +extends = LilyGo_TLora_V2_1_1_6 +build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} + + + +<../examples/simple_room_server> +build_flags = + ${LilyGo_TLora_V2_1_1_6.build_flags} + -D ADVERT_NAME='"TLora-V2.1-1.6 Room"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 diff --git a/variants/promicro_nrf52840/platformio.ini b/variants/promicro_nrf52840/platformio.ini new file mode 100644 index 00000000..afdb70d1 --- /dev/null +++ b/variants/promicro_nrf52840/platformio.ini @@ -0,0 +1,173 @@ +[faketec] +extends = nrf52840_base +board = promicro_nrf52840 +build_src_filter = ${nrf52840_base.build_src_filter} + +build_flags = ${nrf52840_base.build_flags} + -D FAKETEC + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D SX126X_CURRENT_LIMIT=130 + -D SX126X_RX_BOOSTED_GAIN=1 + +[env:Faketec_Repeater] +extends = faketec +build_src_filter = ${faketec.build_src_filter} +<../examples/simple_repeater/main.cpp> +build_flags = + ${faketec.build_flags} + -D ADVERT_NAME="\"Faketec Repeater\"" + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD="\"password\"" +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${faketec.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:Faketec_room_server] +extends = faketec +build_src_filter = ${faketec.build_src_filter} +<../examples/simple_room_server/main.cpp> +build_flags = + ${faketec.build_flags} + -D ADVERT_NAME="\"Test Room\"" + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD="\"password\"" + -D ROOM_PASSWORD="\"hello\"" +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${faketec.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:Faketec_terminal_chat] +extends = faketec +build_flags = + ${faketec.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${faketec.build_src_filter} +<../examples/simple_secure_chat/main.cpp> +lib_deps = + ${faketec.lib_deps} + densaugeo/base64 @ ~1.4.0 + adafruit/RTClib @ ^2.1.3 + +[env:Faketec_companion_radio_usb] +extends = faketec +build_flags = + ${faketec.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 +; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 +; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 +build_src_filter = ${faketec.build_src_filter} +<../examples/companion_radio/main.cpp> +lib_deps = + ${faketec.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0 + +[env:Faketec_companion_radio_ble] +extends = faketec +build_flags = + ${faketec.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 + -D ENABLE_PRIVATE_KEY_EXPORT=1 + -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${faketec.build_src_filter} + +<../examples/companion_radio/main.cpp> +lib_deps = + ${faketec.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0 + +[ProMicroLLCC68] +extends = nrf52840_base +board = promicro_nrf52840 +build_src_filter = ${nrf52840_base.build_src_filter} + +build_flags = ${nrf52840_base.build_flags} + -D FAKETEC + -D RADIO_CLASS=CustomLLCC68 + -D WRAPPER_CLASS=CustomLLCC68Wrapper + -D LORA_TX_POWER=22 + -D SX126X_CURRENT_LIMIT=130 + -D SX126X_RX_BOOSTED_GAIN=1 + +[env:ProMicroLLCC68_Repeater] +extends = ProMicroLLCC68 +build_src_filter = ${ProMicroLLCC68.build_src_filter} +<../examples/simple_repeater/main.cpp> +build_flags = + ${ProMicroLLCC68.build_flags} + -D ADVERT_NAME="\"ProMicroLLCC68 Repeater\"" + -D ADMIN_PASSWORD="\"password\"" +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${ProMicroLLCC68.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:ProMicroLLCC68_room_server] +extends = ProMicroLLCC68 +build_src_filter = ${ProMicroLLCC68.build_src_filter} +<../examples/simple_room_server/main.cpp> +build_flags = + ${ProMicroLLCC68.build_flags} + -D ADVERT_NAME="\"ProMicroLLCC68 Room\"" + -D ADMIN_PASSWORD="\"password\"" + -D ROOM_PASSWORD="\"hello\"" +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${ProMicroLLCC68.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:ProMicroLLCC68_terminal_chat] +extends = ProMicroLLCC68 +build_flags = + ${ProMicroLLCC68.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${ProMicroLLCC68.build_src_filter} +<../examples/simple_secure_chat/main.cpp> +lib_deps = + ${ProMicroLLCC68.lib_deps} + densaugeo/base64 @ ~1.4.0 + adafruit/RTClib @ ^2.1.3 + +[env:ProMicroLLCC68_companion_radio_usb] +extends = ProMicroLLCC68 +build_flags = + ${ProMicroLLCC68.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 +; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 +; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 +build_src_filter = ${ProMicroLLCC68.build_src_filter} +<../examples/companion_radio/main.cpp> +lib_deps = + ${ProMicroLLCC68.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0 + +[env:ProMicroLLCC68_companion_radio_ble] +extends = ProMicroLLCC68 +build_flags = + ${ProMicroLLCC68.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 + -D ENABLE_PRIVATE_KEY_EXPORT=1 + -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${ProMicroLLCC68.build_src_filter} + +<../examples/companion_radio/main.cpp> +lib_deps = + ${ProMicroLLCC68.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0 diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini new file mode 100644 index 00000000..50931655 --- /dev/null +++ b/variants/rak4631/platformio.ini @@ -0,0 +1,102 @@ +[rak4631] +extends = nrf52840_base +platform = https://github.com/maxgerhardt/platform-nordicnrf52.git#rak +board = wiscore_rak4631 +board_check = true +build_flags = ${nrf52840_base.build_flags} + -D RAK_4631 + -D PIN_USER_BTN=9 + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D SX126X_CURRENT_LIMIT=130 + -D SX126X_RX_BOOSTED_GAIN=1 +build_src_filter = ${nrf52840_base.build_src_filter} + + +lib_deps = + ${nrf52840_base.lib_deps} + adafruit/Adafruit SSD1306 @ ^2.5.13 + +[env:RAK_4631_Repeater] +extends = rak4631 +build_flags = + ${rak4631.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"RAK4631 Repeater"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${rak4631.build_src_filter} + + + +<../examples/simple_repeater> + +[env:RAK_4631_room_server] +extends = rak4631 +build_flags = + ${rak4631.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"Test Room"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${rak4631.build_src_filter} + + + +<../examples/simple_room_server> + +[env:RAK_4631_companion_radio_usb] +extends = rak4631 +build_flags = + ${rak4631.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 +; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 +build_src_filter = ${rak4631.build_src_filter} + + + +<../examples/companion_radio> +lib_deps = + ${rak4631.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:RAK_4631_companion_radio_ble] +extends = rak4631 +build_flags = + ${rak4631.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${rak4631.build_src_filter} + + + + + +<../examples/companion_radio> +lib_deps = + ${rak4631.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:RAK_4631_terminal_chat] +extends = rak4631 +build_flags = + ${rak4631.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=1 + -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 +build_src_filter = ${rak4631.build_src_filter} + +<../examples/simple_secure_chat/main.cpp> +lib_deps = + ${rak4631.lib_deps} + densaugeo/base64 @ ~1.4.0 diff --git a/variants/station_g2/platformio.ini b/variants/station_g2/platformio.ini new file mode 100644 index 00000000..c4d1c1b0 --- /dev/null +++ b/variants/station_g2/platformio.ini @@ -0,0 +1,49 @@ +[Station_G2] +extends = esp32_base +board = station-g2 +build_flags = + ${esp32_base.build_flags} + -D STATION_G2 + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=7 +; -D P_LORA_TX_LED=35 +; -D PIN_BOARD_SDA=5 +; -D PIN_BOARD_SCL=6 + -D PIN_USER_BTN=0 + -D SX126X_DIO2_AS_RF_SWITCH=true + -D SX126X_DIO3_TCXO_VOLTAGE=1.8 + -D SX126X_CURRENT_LIMIT=130.0f ; for best TX power! +; -D SX126X_RX_BOOSTED_GAIN=1 - DO NOT ENABLE THIS! +; https://wiki.uniteng.com/en/meshtastic/station-g2#impact-of-lora-node-dense-areashigh-noise-environments-on-rf-performance + +build_src_filter = ${esp32_base.build_src_filter} +lib_deps = + ${esp32_base.lib_deps} + +[env:Station_G2_repeater] +extends = Station_G2 +build_flags = + ${Station_G2.build_flags} + -D ADVERT_NAME='"Station G2 Repeater"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' + -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Station_G2.build_src_filter} + +<../examples/simple_repeater> + +[env:Station_G2_room_server] +extends = Station_G2 +build_src_filter = ${Station_G2.build_src_filter} + +<../examples/simple_room_server> +build_flags = + ${Station_G2.build_flags} + -D ADVERT_NAME='"Station G2 Room"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 diff --git a/variants/t1000-e/platformio.ini b/variants/t1000-e/platformio.ini new file mode 100644 index 00000000..c2f21d9c --- /dev/null +++ b/variants/t1000-e/platformio.ini @@ -0,0 +1,51 @@ +; ----------------- NRF52 T1000e--------------------- +[nrf52840_t1000e] +extends = nrf52_base +platform_packages = framework-arduinoadafruitnrf52 +build_flags = ${nrf52_base.build_flags} + -I src/helpers/nrf52 + -I lib/nrf52/s140_nrf52_7.3.0_API/include + -I lib/nrf52/s140_nrf52_7.3.0_API/include/nrf52 +lib_ignore = + BluetoothOTA + lvgl + lib5b4 +lib_deps = + ${nrf52_base.lib_deps} + rweather/Crypto @ ^0.4.0 + +[t1000-e] +extends = nrf52840_t1000e +board = tracker-t1000-e +board_build.ldscript = boards/nrf52840_s140_v7.ld +build_flags = ${nrf52840_t1000e.build_flags} + -Ivariants/t1000-e + -D T1000_E + -D PIN_USER_BTN=6 + -D USER_BTN_PRESSED=HIGH + -D PIN_STATUS_LED=24 + -D RADIO_CLASS=CustomLR1110 + -D WRAPPER_CLASS=CustomLR1110Wrapper + -D MAX_LORA_TX_POWER=22 +build_src_filter = ${nrf52840_t1000e.build_src_filter} + + + + + +<../variants/t1000-e> +debug_tool = jlink +upload_protocol = nrfutil + +[env:t1000e_companion_radio_ble] +extends = t1000-e +build_flags = ${t1000-e.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 + -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 + -D HAS_UI +build_src_filter = ${t1000-e.build_src_filter} + + + +<../examples/companion_radio/*.cpp> +lib_deps = ${t1000-e.lib_deps} + densaugeo/base64 @ ~1.4.0 diff --git a/variants/t114/platformio.ini b/variants/t114/platformio.ini new file mode 100644 index 00000000..b979f1f4 --- /dev/null +++ b/variants/t114/platformio.ini @@ -0,0 +1,76 @@ +[nrf52840_t114] +extends = nrf52_base +platform_packages = framework-arduinoadafruitnrf52 +build_flags = ${nrf52_base.build_flags} + -I src/helpers/nrf52 + -I lib/nrf52/s140_nrf52_6.1.1_API/include + -I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52 +lib_deps = + ${nrf52_base.lib_deps} + rweather/Crypto @ ^0.4.0 + +[Heltec_t114] +extends = nrf52840_t114 +board = heltec_t114 +board_build.ldscript = boards/nrf52840_s140_v6.ld +build_flags = ${nrf52840_t114.build_flags} + -Ivariants/t114 + -DHELTEC_T114 + -D P_LORA_TX_LED=35 + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D SX126X_CURRENT_LIMIT=130 + -D SX126X_RX_BOOSTED_GAIN=1 +build_src_filter = ${nrf52840_t114.build_src_filter} + + + + + +<../variants/t114> +debug_tool = jlink +upload_protocol = nrfutil + +[env:Heltec_t114_repeater] +extends = Heltec_t114 +build_src_filter = ${Heltec_t114.build_src_filter} + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Heltec_t114.build_flags} + -D ADVERT_NAME='"Heltec_T114 Repeater"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 + +[env:Heltec_t114_room_server] +extends = Heltec_t114 +build_src_filter = ${Heltec_t114.build_src_filter} + +<../examples/simple_room_server> +build_flags = + ${Heltec_t114.build_flags} + -D ADVERT_NAME='"Heltec_T114 Room"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 + +[env:Heltec_t114_companion_radio_ble] +extends = Heltec_t114 +build_flags = + ${Heltec_t114.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_t114.build_src_filter} + + + +<../examples/companion_radio/main.cpp> +lib_deps = + ${Heltec_t114.lib_deps} + densaugeo/base64 @ ~1.4.0 diff --git a/variants/techo/platformio.ini b/variants/techo/platformio.ini new file mode 100644 index 00000000..f2a9432b --- /dev/null +++ b/variants/techo/platformio.ini @@ -0,0 +1,72 @@ +[nrf52840_techo] +extends = nrf52_base +platform_packages = framework-arduinoadafruitnrf52 +build_flags = ${nrf52_base.build_flags} + -I src/helpers/nrf52 + -I lib/nrf52/s140_nrf52_6.1.1_API/include + -I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52 +lib_deps = + ${nrf52_base.lib_deps} + rweather/Crypto @ ^0.4.0 + +[LilyGo_Techo] +extends = nrf52840_techo +board = t-echo +board_build.ldscript = boards/nrf52840_s140_v6.ld +build_flags = ${nrf52840_techo.build_flags} + -Ivariants/techo + -DLILYGO_TECHO + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D SX126X_CURRENT_LIMIT=130 + -D SX126X_RX_BOOSTED_GAIN=1 +build_src_filter = ${nrf52840_techo.build_src_filter} + + + + + +<../variants/techo> +debug_tool = jlink +upload_protocol = nrfutil + +[env:LilyGo_T-Echo_repeater] +extends = LilyGo_Techo +build_src_filter = ${LilyGo_Techo.build_src_filter} +<../examples/simple_repeater/main.cpp> +build_flags = + ${LilyGo_Techo.build_flags} + -D ADVERT_NAME='"T-Echo Repeater"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 + +[env:LilyGo_T-Echo_room_server] +extends = LilyGo_Techo +build_src_filter = ${LilyGo_Techo.build_src_filter} +<../examples/simple_room_server/main.cpp> +build_flags = + ${LilyGo_Techo.build_flags} + -D ADVERT_NAME='"T-Echo Room"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 + +[env:LilyGo_T-Echo_companion_radio_ble] +extends = LilyGo_Techo +build_flags = + ${LilyGo_Techo.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_Techo.build_src_filter} + + + +<../examples/companion_radio/main.cpp> +lib_deps = + ${LilyGo_Techo.lib_deps} + densaugeo/base64 @ ~1.4.0 diff --git a/variants/xiao_c3/platformio.ini b/variants/xiao_c3/platformio.ini new file mode 100644 index 00000000..05688b2d --- /dev/null +++ b/variants/xiao_c3/platformio.ini @@ -0,0 +1,50 @@ +[Xiao_esp32_C3] +extends = esp32_base +board = seeed_xiao_esp32c3 +build_flags = + ${esp32_base.build_flags} + -D LORA_TX_BOOST_PIN=D3 + -D P_LORA_TX_LED=D5 + -D PIN_VBAT_READ=D0 + -D P_LORA_DIO_1=D2 + -D P_LORA_NSS=D4 + -D P_LORA_RESET=RADIOLIB_NC + -D P_LORA_BUSY=D1 + -D PIN_BOARD_SDA=D6 + -D PIN_BOARD_SCL=D7 + -D SX126X_DIO2_AS_RF_SWITCH=true + -D SX126X_DIO3_TCXO_VOLTAGE=1.8 + -D SX126X_CURRENT_LIMIT=130.0f ; for best TX power! + +[env:Xiao_C3_Repeater_sx1262] +extends = Xiao_esp32_C3 +build_src_filter = ${Xiao_esp32_C3.build_src_filter} + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Xiao_esp32_C3.build_flags} + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D SX126X_RX_BOOSTED_GAIN=1 + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"Xiao Repeater"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 + +[env:Xiao_C3_Repeater_sx1268] +extends = Xiao_esp32_C3 +build_src_filter = ${Xiao_esp32_C3.build_src_filter} + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Xiao_esp32_C3.build_flags} + -D RADIO_CLASS=CustomSX1268 + -D WRAPPER_CLASS=CustomSX1268Wrapper + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"Xiao Repeater"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' + ; -D MESH_PACKET_LOGGING=1 + ; -D MESH_DEBUG=1 diff --git a/variants/xiao_s3_wio/platformio.ini b/variants/xiao_s3_wio/platformio.ini new file mode 100644 index 00000000..01931f4f --- /dev/null +++ b/variants/xiao_s3_wio/platformio.ini @@ -0,0 +1,67 @@ +[Xiao_S3_WIO] +extends = esp32_base +board = seeed_xiao_esp32s3 +board_check = true +board_build.mcu = esp32s3 +build_flags = ${esp32_base.build_flags} + -D SEEED_XIAO_S3 + -D P_LORA_DIO_1=39 + -D P_LORA_NSS=41 + -D P_LORA_RESET=42 ; RADIOLIB_NC + -D P_LORA_BUSY=40 ; DIO2 = 38 + -D P_LORA_SCLK=7 + -D P_LORA_MISO=8 + -D P_LORA_MOSI=9 + -D SX126X_DIO2_AS_RF_SWITCH=true + -D SX126X_DIO3_TCXO_VOLTAGE=1.8 + -D SX126X_CURRENT_LIMIT=130 + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D SX126X_RX_BOOSTED_GAIN=1 + +[env:Xiao_S3_WIO_Repeater] +extends = Xiao_S3_WIO +build_src_filter = ${Xiao_S3_WIO.build_src_filter} + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Xiao_S3_WIO.build_flags} + -D ADVERT_NAME='"XiaoS3 Repeater"' + -D ADVERT_LAT=-37.0 + -D ADVERT_LON=145.0 + -D ADMIN_PASSWORD='"password"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 + +[env:Xiao_S3_WIO_terminal_chat] +extends = Xiao_S3_WIO +build_flags = + ${Xiao_S3_WIO.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Xiao_S3_WIO.build_src_filter} + +<../examples/simple_secure_chat/main.cpp> +lib_deps = + ${Xiao_S3_WIO.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:Xiao_S3_WIO_companion_radio_ble] +extends = Xiao_S3_WIO +build_flags = + ${Xiao_S3_WIO.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 +; -D BLE_DEBUG_LOGGING=1 +; -D ENABLE_PRIVATE_KEY_IMPORT=1 +; -D ENABLE_PRIVATE_KEY_EXPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Xiao_S3_WIO.build_src_filter} + + + +<../examples/companion_radio/main.cpp> +lib_deps = + ${Xiao_S3_WIO.lib_deps} + densaugeo/base64 @ ~1.4.0 From 69a6d76b87398a2936de5214c9b718eee186eebf Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Wed, 19 Mar 2025 13:54:43 +1100 Subject: [PATCH 24/28] * experimental workaround for sig verify() bug --- src/Mesh.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 0a0fd769..e309685e 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -228,13 +228,16 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { // check that signature is valid bool is_ok; { - uint8_t message[PUB_KEY_SIZE + 4 + MAX_ADVERT_DATA_SIZE]; + static uint8_t message[PUB_KEY_SIZE + 4 + MAX_ADVERT_DATA_SIZE]; int msg_len = 0; memcpy(&message[msg_len], id.pub_key, PUB_KEY_SIZE); msg_len += PUB_KEY_SIZE; memcpy(&message[msg_len], ×tamp, 4); msg_len += 4; memcpy(&message[msg_len], app_data, app_data_len); msg_len += app_data_len; - is_ok = id.verify(signature, message, msg_len); + static uint8_t sig_copy[SIGNATURE_SIZE]; + memcpy(sig_copy, signature, SIGNATURE_SIZE); + + is_ok = id.verify(sig_copy, message, msg_len); } if (is_ok) { MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): valid advertisement received!", getLogDateTime()); From 4943b388c0a247343ba7afe3e2062b35988e6147 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Wed, 19 Mar 2025 14:31:48 +1100 Subject: [PATCH 25/28] * workaround for Identity::verify() bug. --- src/Mesh.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Mesh.cpp b/src/Mesh.cpp index e309685e..705fdd3c 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -1,5 +1,6 @@ #include "Mesh.h" //#include +#include namespace mesh { @@ -228,16 +229,14 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { // check that signature is valid bool is_ok; { - static uint8_t message[PUB_KEY_SIZE + 4 + MAX_ADVERT_DATA_SIZE]; + uint8_t message[PUB_KEY_SIZE + 4 + MAX_ADVERT_DATA_SIZE]; int msg_len = 0; memcpy(&message[msg_len], id.pub_key, PUB_KEY_SIZE); msg_len += PUB_KEY_SIZE; memcpy(&message[msg_len], ×tamp, 4); msg_len += 4; memcpy(&message[msg_len], app_data, app_data_len); msg_len += app_data_len; - static uint8_t sig_copy[SIGNATURE_SIZE]; - memcpy(sig_copy, signature, SIGNATURE_SIZE); - - is_ok = id.verify(sig_copy, message, msg_len); + //is_ok = id.verify(signature, message, msg_len); + is_ok = Ed25519::verify(signature, id.pub_key, message, msg_len); } if (is_ok) { MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): valid advertisement received!", getLogDateTime()); From 089ac96f2ba6eb3ea6eecbe4eae8aee0a85f2cb5 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Wed, 19 Mar 2025 17:30:35 +1100 Subject: [PATCH 26/28] * verify() fix moved to Identity class --- src/Identity.cpp | 6 ++++++ src/Mesh.cpp | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Identity.cpp b/src/Identity.cpp index e7c57d7e..138c66b7 100644 --- a/src/Identity.cpp +++ b/src/Identity.cpp @@ -2,6 +2,7 @@ #include #define ED25519_NO_SEED 1 #include +#include namespace mesh { @@ -14,7 +15,12 @@ Identity::Identity(const char* pub_hex) { } bool Identity::verify(const uint8_t* sig, const uint8_t* message, int msg_len) const { +#if 0 + // NOTE: memory corruption bug was found in this function!! return ed25519_verify(sig, message, msg_len, pub_key); +#else + return Ed25519::verify(sig, this->pub_key, message, msg_len); +#endif } bool Identity::readFrom(Stream& s) { diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 705fdd3c..0a0fd769 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -1,6 +1,5 @@ #include "Mesh.h" //#include -#include namespace mesh { @@ -235,8 +234,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { memcpy(&message[msg_len], ×tamp, 4); msg_len += 4; memcpy(&message[msg_len], app_data, app_data_len); msg_len += app_data_len; - //is_ok = id.verify(signature, message, msg_len); - is_ok = Ed25519::verify(signature, id.pub_key, message, msg_len); + is_ok = id.verify(signature, message, msg_len); } if (is_ok) { MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): valid advertisement received!", getLogDateTime()); From 4aeafbd0345339187ad277d0d1954ec0b752d975 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Wed, 19 Mar 2025 17:54:55 +1100 Subject: [PATCH 27/28] * companion: added CMD_SET_DEVICE_PIN --- examples/companion_radio/main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 1c973e5c..5c3acb1b 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -184,6 +184,7 @@ static uint32_t _atoi(const char* sp) { #define CMD_SIGN_DATA 34 #define CMD_SIGN_FINISH 35 #define CMD_SEND_TRACE_PATH 36 +#define CMD_SET_DEVICE_PIN 37 #define RESP_CODE_OK 0 #define RESP_CODE_ERR 1 @@ -1402,6 +1403,11 @@ public: } else { writeErrFrame(ERR_CODE_TABLE_FULL); } + } else if (cmd_frame[0] == CMD_SET_DEVICE_PIN && len > 1) { + cmd_frame[len] = 0; // make C string + _prefs.ble_pin = _atoi((char *) &cmd_frame[1]); + savePrefs(); + writeOKFrame(); } else { writeErrFrame(ERR_CODE_UNSUPPORTED_CMD); MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]); From fd55837eecc663f4c45d5d1e0f1db324c3e662a8 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Wed, 19 Mar 2025 18:21:35 +1100 Subject: [PATCH 28/28] * companion: CMD_SET_DEVICE_PIN now uint32 param, RESP_CODE_DEVICE_INFO now includes ble_pin --- examples/companion_radio/main.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 5c3acb1b..088e7de2 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -914,7 +914,7 @@ public: out_frame[i++] = FIRMWARE_VER_CODE; out_frame[i++] = MAX_CONTACTS / 2; // v3+ out_frame[i++] = MAX_GROUP_CHANNELS; // v3+ - memset(&out_frame[i], 0, 4); i += 4; // reserved + memcpy(&out_frame[i], &_prefs.ble_pin, 4); i += 4; memset(&out_frame[i], 0, 12); strcpy((char *) &out_frame[i], FIRMWARE_BUILD_DATE); i += 12; StrHelper::strzcpy((char *) &out_frame[i], board.getManufacturerName(), 40); i += 40; @@ -1403,9 +1403,8 @@ public: } else { writeErrFrame(ERR_CODE_TABLE_FULL); } - } else if (cmd_frame[0] == CMD_SET_DEVICE_PIN && len > 1) { - cmd_frame[len] = 0; // make C string - _prefs.ble_pin = _atoi((char *) &cmd_frame[1]); + } else if (cmd_frame[0] == CMD_SET_DEVICE_PIN && len >= 5) { + memcpy(&_prefs.ble_pin, &cmd_frame[1], 4); savePrefs(); writeOKFrame(); } else {