-
Notifications
You must be signed in to change notification settings - Fork 1
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
Add RIOT federated CoAP example and fix CoapUdpIp channel implementation #142
Conversation
Memory usage after merging this PR will be: Memory Reportaction_empty_test_c
action_microstep_test_c
action_overwrite_test_c
action_test_c
deadline_test_c
delayed_conn_test_c
event_payload_pool_test_c
event_queue_test_c
nanopb_test_c
port_test_c
reaction_queue_test_c
request_shutdown_test_c
startup_test_c
tcp_channel_test_c
timer_test_c
|
Benchmark results after merging this PR: Benchmark resultsPerformance:PingPongUc: PingPongC: ReactionLatencyUc: ReactionLatencyC: Memory usage:PingPongUc: PingPongC: ReactionLatencyUc: ReactionLatencyC: |
Where is |
"Wait for" itself works at least for the sender strangely. I played around with it for quite a bit but haven't found out why it works there but not for the receiver .. I will see further debug it tomorrow |
135f8b0
to
ad40dcc
Compare
3b284a3
to
708bf90
Compare
708bf90
to
b17d4d8
Compare
@erlingrj So I found out why the Is it really needed to have all these things inside of a critical section? I also have some other issues caused by this: I now create a thread to manage the connections of all the CoAP channels. But the problem is the critical section cannot be closed because it first waits until all channels are connected. But that is not possible because the coap thread for handling the connection has not started yet. So we are going in circles :D |
That's a great find! Important detail that
I think we can safely reduce the critical_section here. I am trying to remember why I added it. It must've been to protect against the NetworkChannel thread doing anything inside the runtime (which would be through the callback function passed to it). This callback I think we can safely remove the critical section but we have to be careful with the order in which things are done:
It is important that (2) comes before (3).
That is a good point! I think we can remove the critical section if we are careful in constructing the |
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.
This looks great, if you could just provide some info for how to run the example we can merge this! 👍
|
||
// Inform runtime about new state if it changed from or to NETWORK_CHANNEL_STATE_CONNECTED | ||
if ((old_state == NETWORK_CHANNEL_STATE_CONNECTED && new_state != NETWORK_CHANNEL_STATE_CONNECTED) || | ||
(old_state != NETWORK_CHANNEL_STATE_CONNECTED && new_state == NETWORK_CHANNEL_STATE_CONNECTED)) { | ||
_env->platform->new_async_event(_env->platform); | ||
} | ||
|
||
// Let connection thread evaluate new state of this channel | ||
msg_t msg = { |
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.
So this writes a "msg" to the network thread to notify that the state has been updated. This implies that both runtime and network thread might update the state, I think we discussed earlier to just have the network thread update the state, but this was perhaps only possible for the TcpIp channel?
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.
Yes the issue here is that the TcpIpChannel is polling
. We have a main loop and wait for incoming messages and then depending on what comes in we update the state.
But the RIOT CoAPChannel
is async. Messages come in from the internal gcoap thread
.
So we have a lot of callbacks such as _client_open_connection_callback
etc.
And there is also one place where the runtime changes state which is in open_connection
. This also exists in the current implementation of the TcpIpChannel from what I can see. So if we want to really set it only from one thread maybe we need to fix this also.
A solution here could be to maybe have an extra state variable that is only set by the runtime. (connection_open: bool) or something like that. This one would only be read by the coap / tcpip thread and then they would set their internal state accordingly?
I opened a new Issue (#183). I think this PR is already quite large and since this anyways not only affects the Coap channel alone, maybe we can fix this in a follow up PR?
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.
Thanks for the clarification. Yes open_connection
is there, in the Federated branch I use a mutex now to protect the shared state. I think that is necessary
Okay I have added a readme to the examples folder that explains how to build the various examples including the federated coap example. |
I am currently also in parallel working on a test that we can run in the CI that uses the tap interface and sends some messages between two devices, but I think we should merge this first. I still have some issues with the test that I need to figure out |
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.
Thanks for providing the README, I was still not able to follow it, but it is probably just some minor mistake. I think it might be in the Makefiles?
Get the IP address of the `receiver` by specifying the `PORT=tap1` and `ONLY_PRINT_IP=1` environment variables: | ||
|
||
```shell | ||
make ONLY_PRINT_IP=1 BOARD=native PORT=tap1 all term |
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.
This did not work for me:
$ make ONLY_PRINT_IP=1 BOARD=native PORT=tap1 term
Makefile:36: *** REMOTE_ADDRESS is not defined. Please define it!. Stop.
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.
It should be ONLY_GET_IP
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.
Still confused by the output:
make ONLY_GET_IP=1 BOARD=native PORT=tap1 term
/home/erling/tools/RIOT/dist/tools/pyterm/pyterm -ps /home/erling/dev/reactor-uc/examples/riot/coap_federated/sender/bin/native/lf-coap-federated-sender.elf --process-args tap1
Twisted not available, please install it if you want to use pyterm's JSON capabilities
Welcome to pyterm!
Type '/exit' to exit.
2025-01-08 17:00:25,982 # RIOT native interrupts/signals initialized.
2025-01-08 17:00:25,983 # RIOT native board initialized.
2025-01-08 17:00:25,983 # RIOT native hardware initialization complete.
2025-01-08 17:00:25,983 #
2025-01-08 17:00:25,983 # main(): This is RIOT! (Version: 2024.10)
2025-01-08 17:00:25,983 # [INFO] [NET] IPv6 address: fe80::b020:26ff:fef2:2497
2025-01-08 17:00:25,983 # [INFO] [NET] IPv6 address: f4ff:708:f4ff:708:60bd:608:f3:41dc
2025-01-08 17:00:25,983 # [DEBUG] [NET] CoapUdpIpChannel: Start connection thread
2025-01-08 17:00:25,983 # [INFO] [NET] CoapUdpIpChannel: Register receive callback
2025-01-08 17:00:25,983 # [DEBUG] [ENV] Calculating levels for Reactor MainSender
2025-01-08 17:00:25,983 # [DEBUG] [ENV] Calculating levels for Reactor Sender
2025-01-08 17:00:25,983 # [DEBUG] [ENV] Reaction 0 has level 0
2025-01-08 17:00:25,983 # [DEBUG] [NET] CoapUdpIpChannel: Open connection
2025-01-08 17:00:25,983 # [DEBUG] [NET] CoapUdpIpChannel: Update state: UNINITIALIZED => OPEN
2025-01-08 17:00:25,984 #
2025-01-08 17:00:25,984 # [DEBUG] [NET] CoapUdpIpChannel: Sending 14 bytes
2025-01-08 17:00:25,984 # [DEBUG] [NET] CoapUdpIpChannel: CoAP Message sent
2025-01-08 17:00:25,984 # [DEBUG] [NET] CoapUdpIpChannel: Update state: OPEN => CONNECTION_IN_PROGRESS
2025-01-08 17:00:25,984 #
2025-01-08 17:00:27,386 # [DEBUG] [NET] CoapUdpIpChannel: Client open connection callback
2025-01-08 17:00:27,387 # [ERROR] [NET] CoapUdpIpChannel: TIMEOUT => Try to connect again
2025-01-08 17:00:27,387 # [DEBUG] [NET] CoapUdpIpChannel: Update state: CONNECTION_IN_PROGRESS => CONNECTION_FAILED
2025-01-08 17:00:27,387 #
2025-01-08 17:00:27,387 # [DEBUG] [NET] CoapUdpIpChannel: Sending 14 bytes
2025-01-08 17:00:27,387 # [DEBUG] [NET] CoapUdpIpChannel: CoAP Message sent
2025-01-08 17:00:27,387 # [DEBUG] [NET] CoapUdpIpChannel: Update state: CONNECTION_FAILED => CONNECTION_IN_PROGRESS
2025-01-08 17:00:27,387 #
2025-01-08 17:00:29,773 # [DEBUG] [NET] CoapUdpIpChannel: Client open connection callback
2025-01-08 17:00:29,773 # [ERROR] [NET] CoapUdpIpChannel: TIMEOUT => Try to connect again
2025-01-08 17:00:29,773 # [DEBUG] [NET] CoapUdpIpChannel: Update state: CONNECTION_IN_PROGRESS => CONNECTION_FAILED
...
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.
It should be ONLY_GET_IP
Oups I have renamed it to ONLY_PRINT_IP
everywhere now.
Still confused by the output:
This is very strange. On my computer it only prints the IP Address if ONLY_PRINT_IP
is enabled.
I have rewritten the makefile code again, but it should not change the logic, but is more readable now. Not sure how your system is able to print the IP and the lf_start() code. it should only print the one or the other:
int main() {
#ifdef ONLY_PRINT_IP
print_ip_addresses();
#else
lf_start();
#endif
return 0;
}
As can be seen in the main.c file of the sender and receiver examples. Is your main.c maybe outdated for whatever reason?
Okay should be ready for review again :) 🤓 |
OK I have it running now! It works please check my updates in the README. Hopefully we can find a less manual and error prone way of spinning them up. Easy to mix up how to set |
I 100% agree! :) |
Your changes look good, thank you! |
For some reason the
receive
example fails to sleep whenPlatformRiot_wait_for
is called.I haven't found out why this is the case. But it must be caused somewhere in the runtime. Maybe the thread gets woken up.
With the main.c code from the
sender
it sleepy correctly.I also fixed some bugs in the CoAP channel implementation.