Skip to content

Commit 3e3e364

Browse files
authored
Merge pull request #4 from Quency-D/dev
Merge Dev
2 parents d5bec3d + 4785240 commit 3e3e364

File tree

37 files changed

+733
-137
lines changed

37 files changed

+733
-137
lines changed

build_as_lib.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
from os.path import realpath
2+
3+
Import("env") # type: ignore
4+
menv=env # type: ignore
5+
6+
src_filter = [
7+
'+<*.cpp>',
8+
'+<helpers/*.cpp>',
9+
'+<helpers/sensors>',
10+
'+<helpers/radiolib/*.cpp>',
11+
'+<helpers/ui/MomentaryButton.cpp>',
12+
'+<helpers/ui/buzzer.cpp>',
13+
]
14+
15+
# add build and include dirs according to CPPDEFINES
16+
for item in menv.get("CPPDEFINES", []):
17+
18+
# PLATFORM HANDLING
19+
if item == "STM32_PLATFORM":
20+
src_filter.append("+<helpers/stm32/*>")
21+
elif item == "ESP32":
22+
src_filter.append("+<helpers/esp32/*>")
23+
elif item == "NRF52_PLATFORM":
24+
src_filter.append("+<helpers/nrf52/*>")
25+
elif item == "RP2040_PLATFORM":
26+
src_filter.append("+<helpers/rp2040/*>")
27+
28+
# DISPLAY HANDLING
29+
elif isinstance(item, tuple) and item[0] == "DISPLAY_CLASS":
30+
display_class = item[1]
31+
src_filter.append(f"+<helpers/ui/{display_class}.cpp>")
32+
if (display_class == "ST7789Display") :
33+
src_filter.append(f"+<helpers/ui/OLEDDisplay.cpp>")
34+
src_filter.append(f"+<helpers/ui/OLEDDisplayFonts.cpp>")
35+
36+
# VARIANTS HANDLING
37+
elif isinstance(item, tuple) and item[0] == "MC_VARIANT":
38+
variant_name = item[1]
39+
src_filter.append(f"+<../variants/{variant_name}>")
40+
41+
# INCLUDE EXAMPLE CODE IN BUILD (to provide your own support files without touching the tree)
42+
elif isinstance(item, tuple) and item[0] == "BUILD_EXAMPLE":
43+
example_name = item[1]
44+
src_filter.append(f"+<../examples/{example_name}/*.cpp>")
45+
46+
# EXCLUDE A SOURCE FILE FROM AN EXAMPLE (must be placed after example name or boom)
47+
elif isinstance(item, tuple) and item[0] == "EXCLUDE_FROM_EXAMPLE":
48+
exclude_name = item[1]
49+
if example_name is None:
50+
print("***** PLEASE DEFINE EXAMPLE FIRST *****")
51+
break
52+
src_filter.append(f"-<../examples/{example_name}/{exclude_name}>")
53+
54+
# DEAL WITH UI VARIANT FOR AN EXAMPLE
55+
elif isinstance(item, tuple) and item[0] == "MC_UI_FLAVOR":
56+
ui_flavor = item[1]
57+
if example_name is None:
58+
print("***** PLEASE DEFINE EXAMPLE FIRST *****")
59+
break
60+
src_filter.append(f"+<../examples/{example_name}/{ui_flavor}/*.cpp>")
61+
62+
menv.Replace(SRC_FILTER=src_filter)
63+
64+
#print (menv.Dump())

examples/companion_radio/ui-new/UITask.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,10 @@ class HomeScreen : public UIScreen {
213213
display.setColor(DisplayDriver::GREEN);
214214
display.setTextSize(1);
215215
if (_shutdown_init) {
216-
display.drawTextCentered(display.width() / 2, 34, "shutting down...");
216+
display.drawTextCentered(display.width() / 2, 34, "hibernating...");
217217
} else {
218218
display.drawXbm((display.width() - 32) / 2, 18, power_icon, 32, 32);
219-
display.drawTextCentered(display.width() / 2, 64 - 11, "off: " PRESS_LABEL);
219+
display.drawTextCentered(display.width() / 2, 64 - 11, "hibernate: " PRESS_LABEL);
220220
}
221221
}
222222
return 5000; // next render after 5000 ms
@@ -494,6 +494,20 @@ void UITask::loop() {
494494
c = handleLongPress(KEY_ENTER);
495495
}
496496
#endif
497+
#if defined(WIO_TRACKER_L1)
498+
ev = joystick_left.check();
499+
if (ev == BUTTON_EVENT_CLICK) {
500+
c = checkDisplayOn(KEY_LEFT);
501+
} else if (ev == BUTTON_EVENT_LONG_PRESS) {
502+
c = handleLongPress(KEY_LEFT);
503+
}
504+
ev = joystick_right.check();
505+
if (ev == BUTTON_EVENT_CLICK) {
506+
c = checkDisplayOn(KEY_RIGHT);
507+
} else if (ev == BUTTON_EVENT_LONG_PRESS) {
508+
c = handleLongPress(KEY_RIGHT);
509+
}
510+
#endif
497511

498512
if (c != 0 && curr) {
499513
curr->handleInput(c);

examples/simple_repeater/main.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
159159
}
160160

161161
void putNeighbour(const mesh::Identity& id, uint32_t timestamp, float snr) {
162-
#if MAX_NEIGHBOURS // check if neighbours enabled
162+
#if MAX_NEIGHBOURS // check if neighbours enabled
163163
// find existing neighbour, else use least recently updated
164164
uint32_t oldest_timestamp = 0xFFFFFFFF;
165165
NeighbourInfo* neighbour = &neighbours[0];
@@ -589,7 +589,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
589589
_prefs.cr = LORA_CR;
590590
_prefs.tx_power_dbm = LORA_TX_POWER;
591591
_prefs.advert_interval = 1; // default to 2 minutes for NEW installs
592-
_prefs.flood_advert_interval = 3; // 3 hours
592+
_prefs.flood_advert_interval = 12; // 12 hours
593593
_prefs.flood_max = 64;
594594
_prefs.interference_threshold = 0; // disabled
595595
}
@@ -611,8 +611,8 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
611611
const char* getBuildDate() override { return FIRMWARE_BUILD_DATE; }
612612
const char* getRole() override { return FIRMWARE_ROLE; }
613613
const char* getNodeName() { return _prefs.node_name; }
614-
NodePrefs* getNodePrefs() {
615-
return &_prefs;
614+
NodePrefs* getNodePrefs() {
615+
return &_prefs;
616616
}
617617

618618
void savePrefs() override {
@@ -719,6 +719,17 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
719719
*dp = 0; // null terminator
720720
}
721721

722+
void removeNeighbor(const uint8_t* pubkey, int key_len) override {
723+
#if MAX_NEIGHBOURS
724+
for (int i = 0; i < MAX_NEIGHBOURS; i++) {
725+
NeighbourInfo* neighbour = &neighbours[i];
726+
if(memcmp(neighbour->id.pub_key, pubkey, key_len) == 0){
727+
neighbours[i] = NeighbourInfo(); // clear neighbour entry
728+
}
729+
}
730+
#endif
731+
}
732+
722733
mesh::LocalIdentity& getSelfId() override { return self_id; }
723734

724735
void clearStats() override {

examples/simple_room_server/main.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
298298
// uint32_t now = getRTCClock()->getCurrentTimeUnique();
299299
// memcpy(reply_data, &now, 4); // response packets always prefixed with timestamp
300300
memcpy(reply_data, &sender_timestamp, 4); // reflect sender_timestamp back in response packet (kind of like a 'tag')
301-
301+
302302
switch (payload[0]) {
303303
case REQ_TYPE_GET_STATUS: {
304304
ServerStats stats;
@@ -746,9 +746,9 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
746746
_prefs.tx_power_dbm = LORA_TX_POWER;
747747
_prefs.disable_fwd = 1;
748748
_prefs.advert_interval = 1; // default to 2 minutes for NEW installs
749-
_prefs.flood_advert_interval = 3; // 3 hours
749+
_prefs.flood_advert_interval = 12; // 12 hours
750750
_prefs.flood_max = 64;
751-
_prefs.interference_threshold = 0; // disabled
751+
_prefs.interference_threshold = 0; // disabled
752752
#ifdef ROOM_PASSWORD
753753
StrHelper::strncpy(_prefs.guest_password, ROOM_PASSWORD, sizeof(_prefs.guest_password));
754754
#endif
@@ -778,8 +778,8 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
778778
const char* getBuildDate() override { return FIRMWARE_BUILD_DATE; }
779779
const char* getRole() override { return FIRMWARE_ROLE; }
780780
const char* getNodeName() { return _prefs.node_name; }
781-
NodePrefs* getNodePrefs() {
782-
return &_prefs;
781+
NodePrefs* getNodePrefs() {
782+
return &_prefs;
783783
}
784784

785785
void savePrefs() override {

examples/simple_sensor/SensorMesh.cpp

Lines changed: 72 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,23 @@ void SensorMesh::getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) {
613613
}
614614
}
615615

616+
void SensorMesh::sendAckTo(const ContactInfo& dest, uint32_t ack_hash) {
617+
if (dest.out_path_len < 0) {
618+
mesh::Packet* ack = createAck(ack_hash);
619+
if (ack) sendFlood(ack, TXT_ACK_DELAY);
620+
} else {
621+
uint32_t d = TXT_ACK_DELAY;
622+
if (getExtraAckTransmitCount() > 0) {
623+
mesh::Packet* a1 = createMultiAck(ack_hash, 1);
624+
if (a1) sendDirect(a1, dest.out_path, dest.out_path_len, d);
625+
d += 300;
626+
}
627+
628+
mesh::Packet* a2 = createAck(ack_hash);
629+
if (a2) sendDirect(a2, dest.out_path, dest.out_path_len, d);
630+
}
631+
}
632+
616633
void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) {
617634
int i = matching_peer_indexes[sender_idx];
618635
if (i < 0 || i >= num_contacts) {
@@ -656,45 +673,71 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i
656673
memcpy(&sender_timestamp, data, 4); // timestamp (by sender's RTC clock - which could be wrong)
657674
uint flags = (data[4] >> 2); // message attempt number, and other flags
658675

659-
if (!(flags == TXT_TYPE_CLI_DATA)) {
660-
MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported text type received: flags=%02x", (uint32_t)flags);
661-
} else if (sender_timestamp > from.last_timestamp) { // prevent replay attacks
662-
from.last_timestamp = sender_timestamp;
663-
from.last_activity = getRTCClock()->getCurrentTime();
664-
665-
// len can be > original length, but 'text' will be padded with zeroes
666-
data[len] = 0; // need to make a C string again, with null terminator
667-
668-
uint8_t temp[166];
669-
char *command = (char *) &data[5];
670-
char *reply = (char *) &temp[5];
671-
handleCommand(sender_timestamp, command, reply);
672-
673-
int text_len = strlen(reply);
674-
if (text_len > 0) {
675-
uint32_t timestamp = getRTCClock()->getCurrentTimeUnique();
676-
if (timestamp == sender_timestamp) {
677-
// WORKAROUND: the two timestamps need to be different, in the CLI view
678-
timestamp++;
679-
}
680-
memcpy(temp, &timestamp, 4); // mostly an extra blob to help make packet_hash unique
681-
temp[4] = (TXT_TYPE_CLI_DATA << 2);
682-
683-
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, from.id, secret, temp, 5 + text_len);
684-
if (reply) {
685-
if (from.out_path_len < 0) {
686-
sendFlood(reply, CLI_REPLY_DELAY_MILLIS);
676+
if (sender_timestamp > from.last_timestamp) { // prevent replay attacks
677+
if (flags == TXT_TYPE_PLAIN) {
678+
bool handled = handleIncomingMsg(from, sender_timestamp, &data[5], flags, len - 5);
679+
if (handled) { // if msg was handled then send an ack
680+
uint32_t ack_hash; // calc truncated hash of the message timestamp + text + sender pub_key, to prove to sender that we got it
681+
mesh::Utils::sha256((uint8_t *) &ack_hash, 4, data, 5 + strlen((char *)&data[5]), from.id.pub_key, PUB_KEY_SIZE);
682+
683+
if (packet->isRouteFlood()) {
684+
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the ACK
685+
mesh::Packet* path = createPathReturn(from.id, secret, packet->path, packet->path_len,
686+
PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4);
687+
if (path) sendFlood(path, TXT_ACK_DELAY);
687688
} else {
688-
sendDirect(reply, from.out_path, from.out_path_len, CLI_REPLY_DELAY_MILLIS);
689+
sendAckTo(from, ack_hash);
690+
}
691+
}
692+
} else if (flags == TXT_TYPE_CLI_DATA) {
693+
from.last_timestamp = sender_timestamp;
694+
from.last_activity = getRTCClock()->getCurrentTime();
695+
696+
// len can be > original length, but 'text' will be padded with zeroes
697+
data[len] = 0; // need to make a C string again, with null terminator
698+
699+
uint8_t temp[166];
700+
char *command = (char *) &data[5];
701+
char *reply = (char *) &temp[5];
702+
handleCommand(sender_timestamp, command, reply);
703+
704+
int text_len = strlen(reply);
705+
if (text_len > 0) {
706+
uint32_t timestamp = getRTCClock()->getCurrentTimeUnique();
707+
if (timestamp == sender_timestamp) {
708+
// WORKAROUND: the two timestamps need to be different, in the CLI view
709+
timestamp++;
710+
}
711+
memcpy(temp, &timestamp, 4); // mostly an extra blob to help make packet_hash unique
712+
temp[4] = (TXT_TYPE_CLI_DATA << 2);
713+
714+
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, from.id, secret, temp, 5 + text_len);
715+
if (reply) {
716+
if (from.out_path_len < 0) {
717+
sendFlood(reply, CLI_REPLY_DELAY_MILLIS);
718+
} else {
719+
sendDirect(reply, from.out_path, from.out_path_len, CLI_REPLY_DELAY_MILLIS);
720+
}
689721
}
690722
}
723+
} else {
724+
MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported text type received: flags=%02x", (uint32_t)flags);
691725
}
692726
} else {
693727
MESH_DEBUG_PRINTLN("onPeerDataRecv: possible replay attack detected");
694728
}
695729
}
696730
}
697731

732+
bool SensorMesh::handleIncomingMsg(ContactInfo& from, uint32_t timestamp, uint8_t* data, uint flags, size_t len) {
733+
MESH_DEBUG_PRINT("handleIncomingMsg: unhandled msg from ");
734+
#ifdef MESH_DEBUG
735+
mesh::Utils::printHex(Serial, from.id.pub_key, PUB_KEY_SIZE);
736+
Serial.printf(": %s\n", data);
737+
#endif
738+
return false;
739+
}
740+
698741
bool SensorMesh::onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) {
699742
int i = matching_peer_indexes[sender_idx];
700743
if (i < 0 || i >= num_contacts) {

examples/simple_sensor/SensorMesh.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ class SensorMesh : public mesh::Mesh, public CommonCLICallbacks {
140140
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
141141
bool onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override;
142142
void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) override;
143-
143+
virtual bool handleIncomingMsg(ContactInfo& from, uint32_t timestamp, uint8_t* data, uint flags, size_t len);
144+
void sendAckTo(const ContactInfo& dest, uint32_t ack_hash);
144145
private:
145146
FILESYSTEM* _fs;
146147
unsigned long next_local_advert, next_flood_advert;

library.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "MeshCore",
3+
"version" : "1.7.4",
4+
"dependencies": {
5+
"SPI": "*",
6+
"Wire": "*",
7+
"jgromes/RadioLib": "^7.1.2",
8+
"rweather/Crypto": "^0.4.0",
9+
"adafruit/RTClib": "^2.1.3",
10+
"melopero/Melopero RV3028": "^1.1.0",
11+
"electroniccats/CayenneLPP": "1.4.0"
12+
},
13+
"build": {
14+
"extraScript": "build_as_lib.py"
15+
}
16+
}

platformio.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ build_src_filter =
4747
+<*.cpp>
4848
+<helpers/*.cpp>
4949
+<helpers/radiolib/*.cpp>
50+
+<helpers/ui/MomentaryButton.cpp>
5051

5152
; ----------------- ESP32 ---------------------
5253

@@ -114,12 +115,14 @@ build_flags =
114115
-D ENV_INCLUDE_LPS22HB=1
115116
-D ENV_INCLUDE_INA3221=1
116117
-D ENV_INCLUDE_INA219=1
118+
-D ENV_INCLUDE_INA226=1
117119
-D ENV_INCLUDE_INA260=1
118120
-D ENV_INCLUDE_MLX90614=1
119121
-D ENV_INCLUDE_VL53L0X=1
120122
lib_deps =
121123
adafruit/Adafruit INA3221 Library @ ^1.0.1
122124
adafruit/Adafruit INA219 @ ^1.2.3
125+
robtillaart/INA226 @ ^0.6.4
123126
adafruit/Adafruit INA260 Library @ ^1.5.3
124127
adafruit/Adafruit AHTX0 @ ^2.0.5
125128
adafruit/Adafruit BME280 Library @ ^2.3.0

src/helpers/CommonCLI.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,17 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
165165
}
166166
} else if (memcmp(command, "neighbors", 9) == 0) {
167167
_callbacks->formatNeighborsReply(reply);
168+
} else if (memcmp(command, "neighbor.remove ", 16) == 0) {
169+
const char* hex = &command[16];
170+
uint8_t pubkey[PUB_KEY_SIZE];
171+
int hex_len = min((int)strlen(hex), PUB_KEY_SIZE*2);
172+
int pubkey_len = hex_len / 2;
173+
if (mesh::Utils::fromHex(pubkey, pubkey_len, hex)) {
174+
_callbacks->removeNeighbor(pubkey, pubkey_len);
175+
strcpy(reply, "OK");
176+
} else {
177+
strcpy(reply, "ERR: bad pubkey");
178+
}
168179
} else if (memcmp(command, "tempradio ", 10) == 0) {
169180
strcpy(tmp, &command[10]);
170181
const char *parts[5];

src/helpers/CommonCLI.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ class CommonCLICallbacks {
4343
virtual void dumpLogFile() = 0;
4444
virtual void setTxPower(uint8_t power_dbm) = 0;
4545
virtual void formatNeighborsReply(char *reply) = 0;
46+
virtual void removeNeighbor(const uint8_t* pubkey, int key_len) {
47+
// no op by default
48+
};
4649
virtual mesh::LocalIdentity& getSelfId() = 0;
4750
virtual void clearStats() = 0;
4851
virtual void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) = 0;

0 commit comments

Comments
 (0)