diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 03bd1065..088e7de2 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -96,10 +96,18 @@ #include #include static TechoBoard board; + +#elif defined(LILYGO_TBEAM) + #include + #include + static TBeamBoard board; + #elif defined(FAKETEC) #include #include + #include static faketecBoard board; + #else #error "need to provide a 'board' object" #endif @@ -130,7 +138,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 "13 Mar 2025" @@ -175,6 +183,8 @@ 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 CMD_SET_DEVICE_PIN 37 #define RESP_CODE_OK 0 #define RESP_CODE_ERR 1 @@ -183,8 +193,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 @@ -192,7 +202,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 -// ... _V3 stuff in here +#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) #define RESP_CODE_CHANNEL_INFO 18 // a reply to CMD_GET_CHANNEL #define RESP_CODE_SIGN_START 19 #define RESP_CODE_SIGNATURE 20 @@ -207,6 +218,14 @@ 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 + +#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 /* -------------------------------------------------------------------------------------- */ @@ -233,11 +252,9 @@ 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; BaseSerialInterface* _serial; - unsigned long last_msg_sent; ContactsIterator _iter; uint32_t _iter_filter_since; uint32_t _most_recent_lastmod; @@ -256,6 +273,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 @@ -432,10 +457,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() { @@ -546,26 +572,35 @@ 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); } - 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) { @@ -590,27 +625,36 @@ 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++] = findChannelIdx(channel); - 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 ?? @@ -628,7 +672,7 @@ protected: soundBuzzer(); } #ifdef HAS_UI - ui_task.newMsg(in_path_len < 0 ? 0xFF : in_path_len, "Public", text, offline_queue_len); + ui_task.newMsg(path_len, "Public", text, offline_queue_len); #endif } @@ -685,6 +729,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); } @@ -706,6 +769,7 @@ public: app_target_ver = 0; _identity_store = NULL; pending_login = pending_status = 0; + next_ack_idx = 0; sign_data = NULL; // defaults @@ -850,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; @@ -901,26 +965,31 @@ 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(); + writeErrFrame(ERR_CODE_TABLE_FULL); } 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); } } 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; @@ -930,16 +999,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); @@ -978,7 +1051,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]; @@ -994,7 +1067,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); @@ -1006,7 +1079,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]; @@ -1017,7 +1090,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]; @@ -1036,7 +1109,7 @@ public: saveContacts(); writeOKFrame(); } else { - writeErrFrame(); // table is full! + writeErrFrame(ERR_CODE_TABLE_FULL); } } } else if (cmd_frame[0] == CMD_REMOVE_CONTACT) { @@ -1046,15 +1119,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]; @@ -1062,7 +1139,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) { @@ -1074,7 +1151,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]; @@ -1084,14 +1161,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; @@ -1129,11 +1206,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(); @@ -1174,7 +1251,7 @@ public: self_id = identity; writeOKFrame(); } else { - writeErrFrame(); + writeErrFrame(ERR_CODE_FILE_IO_ERROR); } #else writeDisabledFrame(); @@ -1189,10 +1266,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]; @@ -1203,7 +1280,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() @@ -1214,7 +1291,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]; @@ -1223,7 +1300,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() @@ -1234,14 +1311,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]; @@ -1258,10 +1335,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; @@ -1272,7 +1349,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; @@ -1288,7 +1365,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); @@ -1304,10 +1381,34 @@ 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; + 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); + + 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(ERR_CODE_TABLE_FULL); + } + } else if (cmd_frame[0] == CMD_SET_DEVICE_PIN && len >= 5) { + memcpy(&_prefs.ble_pin, &cmd_frame[1], 4); + savePrefs(); + writeOKFrame(); } else { - writeErrFrame(); + writeErrFrame(ERR_CODE_UNSUPPORTED_CMD); MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]); } } @@ -1377,6 +1478,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/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 23bcb2c0..9e21402b 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -107,6 +107,7 @@ #elif defined(FAKETEC) #include #include + #include static faketecBoard board; #else #error "need to provide a 'board' object" @@ -161,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; @@ -173,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 @@ -219,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) { @@ -245,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"); @@ -494,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); + } + } } } } @@ -588,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; } diff --git a/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index 248353aa..e695fa03 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" @@ -258,8 +259,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 @@ -267,16 +268,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/platformio.ini b/platformio.ini index 78078780..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,685 +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 ; ----------------- NRF52 --------------------- [nrf52_base] @@ -729,406 +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 - -D DISPLAY_CLASS=SSD1306Display - -D PIN_BOARD_SCL=7 - -D PIN_BOARD_SDA=8 - -D PIN_OLED_RESET=-1 - -D PIN_USER_BTN=6 -lib_deps= - ${nrf52840_base.lib_deps} - adafruit/Adafruit SSD1306 @ ^2.5.13 - -[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=0 - -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> + -lib_deps = - ${faketec.lib_deps} - adafruit/RTClib @ ^2.1.3 - densaugeo/base64 @ ~1.4.0 \ No newline at end of file diff --git a/src/Dispatcher.cpp b/src/Dispatcher.cpp index dffabcc3..65f9687f 100644 --- a/src/Dispatcher.cpp +++ b/src/Dispatcher.cpp @@ -115,6 +115,7 @@ void Dispatcher::checkRecv() { } else { memcpy(pkt->payload, &raw[i], pkt->payload_len); + pkt->_snr = _radio->getLastSNR() * 4.0f; score = _radio->packetScore(_radio->getLastSNR(), len); air_time = _radio->getEstAirtimeFor(len); } @@ -129,7 +130,7 @@ void Dispatcher::checkRecv() { Serial.print(getLogDateTime()); Serial.printf(": RX, len=%d (type=%d, route=%s, payload_len=%d) SNR=%d RSSI=%d score=%d", 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)); static uint8_t packet_hash[MAX_HASH_SIZE]; pkt->calculatePacketHash(packet_hash); @@ -233,6 +234,7 @@ Packet* Dispatcher::obtainNewPacket() { n_full_events++; } else { pkt->payload_len = pkt->path_len = 0; + pkt->_snr = 0; } return pkt; } 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 95a1d6d7..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! @@ -79,7 +103,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { 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("%s Mesh::onRecvPacket(): incomplete data packet", getLogDateTime()); } else if (!_tables->hasSeen(pkt)) { // NOTE: this is a 'first packet wins' impl. When receiving from multiple paths, the first to arrive wins. @@ -333,7 +357,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) { - if (data_len + 2 + CIPHER_BLOCK_SIZE-1 > MAX_PACKET_PAYLOAD) return NULL; + if (data_len + CIPHER_MAC_SIZE + CIPHER_BLOCK_SIZE-1 > MAX_PACKET_PAYLOAD) return NULL; } else { return NULL; // invalid type } @@ -433,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; @@ -455,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 4647464e..cfacebc9 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -100,9 +100,22 @@ 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 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 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) * NOTE: these can be received multiple times (per sender), via differen routes @@ -182,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 @@ -197,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 a342c37f..e338b60d 100644 --- a/src/Packet.cpp +++ b/src/Packet.cpp @@ -10,11 +10,13 @@ Packet::Packet() { payload_len = 0; } - 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); } diff --git a/src/Packet.h b/src/Packet.h index bff04321..e20b3a49 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_RAW_CUSTOM 0x0F // custom packet as raw bytes, for applications with custom encryption, payloads, etc @@ -44,6 +45,7 @@ public: uint16_t payload_len, path_len; uint8_t path[MAX_PATH_SIZE]; uint8_t payload[MAX_PACKET_PAYLOAD]; + int8_t _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 ((float)_snr) / 4.0f; } + /** * \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 99fd942a..eb6116e7 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); @@ -222,7 +222,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 ec603a7e..30598f6c 100644 --- a/src/helpers/BaseChatMesh.h +++ b/src/helpers/BaseChatMesh.h @@ -106,13 +106,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; // storage concepts, for sub-classes to override/implement 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; } diff --git a/src/helpers/TBeamBoard.h b/src/helpers/TBeamBoard.h new file mode 100644 index 00000000..fc0d3b73 --- /dev/null +++ b/src/helpers/TBeamBoard.h @@ -0,0 +1,82 @@ +#pragma once + + +#include +#include +#include "XPowersLib.h" + +// Defined using AXP2102 +#define XPOWERS_CHIP_AXP2101 + +// 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 { + XPowersAXP2101 power; + +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"; + } +}; 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