-
Notifications
You must be signed in to change notification settings - Fork 139
Bridge/cross repeater implementation #454
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
I think this could be done in a much simpler way. Also, modifying the Dispatcher class is not necessary, or desirable. |
I had a design principle behind it: Which lead to the current "parallel" architecture and the usage of queues. If serialisation happens inside logRx() then the RF cycle needs to wait for the serial shenanigans to happen; if this is not a issue then it can be simplified indeed. I'm fine to make it much more leaner. But the serial packet abstraction would still be a valid choice as it's easier to parse the stream of data, and the added CRC keeps things sane.. think about noise environments, long unshielded serial cables etc. |
This is definitely something I've been looking for. Thank you @jbrazio |
This one open very cool use cases ! I've made some experiments out of curiosity and could make it work with RAK3272 (based on stm32), I published my own branch here : feel free to incorporate the stm32 bits ;) Results were mixed when I tried with esp32-s3 on the lora side, acks were not going through (or maybe took too long), but results were better with stm32 |
thanks @fdlamotte I will merge your code as I didn't had any STM32 boards to test. |
@fdlamotte and @jbrazio you're both legends. I'm looking forward to studying the code from both of your repo's and coming up with something for my own use. Got most of the C fundamentals down, currently learning Go, and my next stop is C++ for embedded, so this will help a lot. I really appreciate you sharing your work. |
still playing with your code @jbrazio ;) I've tried to get rid of modifications in dispatcher as proposed by @ripplebiz used Forgot the link: fdlamotte@22656d5 I think I now want a RAK11162 more than ever: https://docs.rakwireless.com/product-categories/wisblock/rak11162/overview/ |
I feel that a transparent bridge is less desirable, just because in the end of the day we are actually adding an additional hop to the path of the packet. There is also a debate within our local CORE community, should we add options (flags) to allow packet filtering at the bridge. The most discussed example is the public channel:
|
Very interesting topics and I think this is generally related to repeater, not only bridges (one more reason not to have transparent bridges) ... My own interpretation is that we could have some control at the repeater level for filtering nodes/channel and even some whitelist/blacklist mechanisms depending on source or destination Also, we should be able to specify the number of hops we want for a channel message (I think this is possible at the packet level, but don't know if any application can use this, meshcli don't give that control for instance). That could be interesting to send public messages locally (0 hop away) |
…directly in the repeater source code.
@ripplebiz please review the latest patch. |
on my side it seems ok. You should probably discard the changes to dispatcher ... just doing some tests ... with this version the repeater hangs at some point |
Where does it get stuck ? Is it on serial read ? |
I'll try to investigate, first I've rolled back to what I was using this morning ;) as I was not in the same place to check if it was still working ;) ... because the setup is not that simple and an error on my side was possible |
I'm sorry, can't get it to work reliably (lots of acks are missed) and debug is very difficult It has been hanging less though edit: removed debug, hangs more quickly, probably a synchro issue ... the queue you had before was good for that kind of problems ;) |
it hangs at but I have to backtrace (I get the cpu in an exception) and don't know yet what happens that get there or the values of the counters |
len = 65535 ;) => that's what causes the boom ... |
Strange.. could this be a stm32 thing ? I've got my dev bridge running and no hangs but it's on rp2040.
|
either overflow, or some return code at -1 on the other side (esp32c3 with espnow for me) to calculate length. And yes this can be related to stm32 (some default behavior not working the same) I have the tools set up now, I'll continue investigating ...
|
In which line is it breaking ?
|
Packets come with a size of -1 They are transmitted (from the esp side), because Then it breaks at In your earlier version this was checked I think you just have to write : |
Try the latest version. |
This is indeed a very special case.. how were you getting it so often ? It needs to have a full packet on buffer with the right magic but followed by a broken read (-1 cast to uint8_t right after the magic). As len was not being verified for sanity before the data being copied to pkt payload, it would overflow and overwrite memory leading to a crash. |
Yes, that's why I'm not really sure ... But in the end the last version works well with no other mitigation ! to be more cautious, you could read the serial port in an int and check for a negative value (and discard in this case) ... but this does not seem to happen any more edit: Won't do more for today ... but it's been very cool ;) |
examples/simple_repeater/main.cpp
Outdated
#endif | ||
} else { | ||
pkt->readFrom(bytes, len); | ||
_mgr->queueInbound(pkt, millis()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of millis(), should be futureMillis(0)
@@ -292,6 +315,22 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks { | |||
} | |||
} | |||
void logTx(mesh::Packet* pkt, int len) override { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty sure this should be logRx()
You want to send received packets over to the other side of the bridge.
If you send transmitted packets, you will also be sending back packets that came FROM the other side of bridge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we use logRx() instead of logTx() then packets originated ON the bridge itself will not be sent over the bridge (adverts etc). So it makes impossible to manage bridge A from bridge B. Using logTx() we get duplicated packets on the serial line, but the hashing mechanism will prevent them from being transmitted over RF.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exactly what I've noticed ... and why I used logtx yesterday
valid point, but there is a lot more to do when sending from logRx() I won't be able to tackle this today, but here is a log my bridge was still up this morning ;) : edit: smaller log ;) just doing clock sync and clock from espnow side towards esp32 repeater (that is bridged)
the ones at 7:36:03 (RX and TX) are indeed suspects of the kind of behavior pointed out by scott |
A better one:
Log from
Log from
|
will test this afternoon (edit: I get the same traces ;) ) do you think we could have an abstract Bridge (MeshBridge ?) class and one implementation as SerialBridge ? this would be lighter than your first implementation, but also pluggable ;) |
I like this idea. Opens the door to other bridge implementations in a standardised way. |
For the problem of reflecting back packets that were inserted (with queueInbound()), when hooking into logTx(), you could have your own SimpleMeshTables instance, and call hasSeen() before queueInbound(), then in LogTx() have an if (!hasSeen()) ... write to serial bridge .... Like @fdlamotte mentioned, would be good to have a separate SerialBridge class that inherits from some AbstractBridge class (prob only needs two abstract methods), and this class could have a SimpleMeshTables instance as a member. |
I'm also thinking about having several bridges on the same repeater ! to have some sort of hub ;) |
Okay this goes a step back into the direction I had it initially which is fine. Here we are a bit limited by the number of serial ports on the devices, usually 0 is the root, 1 is taken mostly by gps and 2 is here being used for bridging. To think about a "hub" it would be better implemented using a real network stack. I've been really cautious to use a physical serial connection and not network.. just because I don't want to be the one to blame to bring MqTT to Meshcore. 🥸 |
I was thinking about custom builds ... For me its one strong point with MC, hw/sw bricks that you can assemble as you wish, your bridge will fit well in that philosophy |
well messenging over mqtt would be bad (and I agree we should not bridge over the internet in general) ... but I'm sure there are valid uses in mqtt, to monitor the network for instance (just collecting adverts and neighbours could give usefull information) |
You already built the right tool for the job ! Your python API, I'm using it to map the network remotely. |
I don't know where my mind was going ... I've been using MT again after 6 month (because there is some activity in the region) and you can already see the bad effects it has on me ! No MQTT inside nodes for sure ;) |
c533821
to
04042e3
Compare
Overview
This PR offers a solution for bridging two meshcore networks, enabling connectivity between:
Essentially, we create a bridge by using two repeaters interconnected via a serial port. The serial method was chosen because it ensures full compliance with an off-grid protocol by not relying on external networks or internet-based protocols, such as MQTT, that are prone to failure in emergency situations, while still opening up many new possibilities without compromising the RF only principle.
All types of traffic appear to be functioning properly, including paths, pings, administrative requests and direct messaging between clients on different bands. However, it is important to note that this solution should not be considered production-ready and requires further testing.
Configuration
To enable, open
variants/your_board_here/platformio.ini
, edit theRepeater
configuration and add the following defines:You can download pre-built test versions of this PR.
Flash them using the option
Custom Firmware
from the official flasher.Pinout
Suggested IO ports to be used by each type of board:
[Serial2, tx=6, rx=5]
[Serial2, tx=8, rx=9]
[Serial2, tx=25, rx=34]