Skip to content

Commit

Permalink
Add RIOT federated CoAP example and fix CoapUdpIp channel implementat…
Browse files Browse the repository at this point in the history
…ion (#142)

* Add RIOT federated CoAP example and fix CoAP channel

* Fix after merging main

* Improve coap channel

* Add connection thread to keep channels connected

* Fix riot critical section?

* Remove critical section in LF_ENTRY_POINT_FEDERATED for now

* Print ip address if channel is not found

* Add readme explaining how to run RIOT examples

* Fix readme example paths

* Improve the readme for the examples

* Rename only_get_ip to only_print_ip env variable

* Update examples/riot/coap_federated/receiver/Makefile

Co-authored-by: erling <erling.jellum@gmail.com>

* Also remove tcp_ip from sender

* Make makefile more readable

* Rewrite make again

* Add explanation on what ip address to choose

* Update README

---------

Co-authored-by: erling <erling.jellum@gmail.com>
  • Loading branch information
LasseRosenow and erlingrj authored Jan 10, 2025
1 parent b3c391a commit b09c2ed
Show file tree
Hide file tree
Showing 8 changed files with 501 additions and 18 deletions.
96 changes: 96 additions & 0 deletions examples/riot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# RIOT Examples

This doc explains how to compile and run the various RIOT OS examples.

## Setup RIOT Environment

Make sure that the environment variable `RIOTBASE` points to a `RIOT` codebase.

## Build and Run

### Blinky

```shell
cd blinky
make BOARD=native all term
```

### Hello

```shell
cd hello
make BOARD=native all term
```

### CoAP Federated

The federated example using CoAP channels needs to be run using 2 terminals.
Make sure to set the `PORT` environment variable to the correct `tap` interface such as `tap0` or `tap1` as can be seen in the code below.

#### Preparation

First you need to create the `tap` interfaces so that the `sender` and `receiver` application can communicate through the (linux) host.

```shell
sudo $RIOTBASE/dist/tools/tapsetup/tapsetup
```

#### Get IPv6 address of receiver

Enter the directory of the `sender` application:

```shell
cd coap_federated/sender
```

Get the IP address of the `receiver` by specifying the `PORT=tap1` and `ONLY_PRINT_IP=1` environment variables:

*If the program returns more than one IP-Address then select the one that starts with `fe80`*.

```shell
make ONLY_PRINT_IP=1 BOARD=native PORT=tap1 all term
```

The resulting program will print out the IPv6 address of `tap1` and terminate.
This address must be used when starting the sender below.


#### Get IPv6 address of sender

Enter the directory of the `receiver` application:

```shell
cd coap_federated/receiver
```

Get the IP address of the `sender` by specifying the `PORT=tap0` and `ONLY_PRINT_IP=1` environment variables:

*If the program returns more than one IP-Address then select the one that starts with `fe80`*.

```shell
make ONLY_PRINT_IP=1 BOARD=native PORT=tap0 all term
```

The resulting program will print out the IPv6 address of `tap0` and terminate.
This address must be used when starting the receiver below.

#### Start the applications

##### Sender
Start the sender with `PORT=tap0`, make sure to replace `REMOTE_ADDRESS` with
the address of `tap1` that you found above.

```shell
cd sender
make REMOTE_ADDRESS=fe80::8cc3:33ff:febb:1b3 BOARD=native PORT=tap0 all term
```

##### Receiver

Start the receiver with `PORT=tap1`, make sure to replace `REMOTE_ADDRESS` with
the address of `tap0` that you found above.

```shell
cd receiver
make REMOTE_ADDRESS=fe80::44e5:1bff:fee4:dac8 BOARD=native PORT=tap1 all term
```
45 changes: 45 additions & 0 deletions examples/riot/coap_federated/receiver/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# name of your application
APPLICATION = lf-coap-federated-receiver

# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/../../../../../RIOT

# If no BOARD is found in the environment, use this default:
BOARD ?= native

# Comment this out to disable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
DEVELHELP ?= 1

# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1

# Enable reactor-uc features
CFLAGS += -DNETWORK_CHANNEL_COAP_RIOT
REACTION_QUEUE_SIZE = 32
EVENT_QUEUE_SIZE = 32

CFLAGS += -DTHREAD_STACKSIZE_DEFAULT=10000
CFLAGS += -DTHREAD_STACKSIZE_MAIN=10000
CFLAGS += -DISR_STACKSIZE=10000

# Configure CoAP retransmission timeout
CFLAGS += -DCONFIG_GCOAP_NO_RETRANS_BACKOFF=1
CFLAGS += -DCONFIG_COAP_ACK_TIMEOUT_MS=400
CFLAGS += -DCONFIG_COAP_MAX_RETRANSMIT=4

# Check if ONLY_PRINT_IP is defined
# If ONLY_PRINT_IP is defined the REMOTE_ADDRESS is not needed
ifdef ONLY_PRINT_IP
# ONLY_PRINT_IP is defined => Set CFLAGS for it
CFLAGS += -DONLY_PRINT_IP=$(ONLY_PRINT_IP)
else ifdef REMOTE_ADDRESS
# REMOTE_ADDRESS is defined => Set CFLAGS for it
CFLAGS += -DREMOTE_ADDRESS=\"$(REMOTE_ADDRESS)\"
else
# Neither is defined
$(error Either define REMOTE_ADDRESS or set ONLY_PRINT_IP=1 to print the IP-Address of this device.)
endif

include $(CURDIR)/../../../../make/riot/riot.mk
117 changes: 117 additions & 0 deletions examples/riot/coap_federated/receiver/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include "reactor-uc/platform/riot/coap_udp_ip_channel.h"
#include "reactor-uc/reactor-uc.h"

#ifndef REMOTE_ADDRESS
#define REMOTE_ADDRESS "fe80::44e5:1bff:fee4:dac8"
#endif

#define REMOTE_PROTOCOL_FAMILY AF_INET6

typedef struct {
int size;
char msg[512];
} lf_msg_t;

lf_ret_t deserialize_msg_t(void *user_struct, const unsigned char *msg_buf, size_t msg_size) {
(void)msg_size;

lf_msg_t *msg = user_struct;
memcpy(&msg->size, msg_buf, sizeof(msg->size));
memcpy(msg->msg, msg_buf + sizeof(msg->size), msg->size);

return LF_OK;
}

LF_DEFINE_REACTION_STRUCT(Receiver, r, 0)
LF_DEFINE_REACTION_CTOR(Receiver, r, 0)
LF_DEFINE_INPUT_STRUCT(Receiver, in, 1, 0, lf_msg_t, 0)
LF_DEFINE_INPUT_CTOR(Receiver, in, 1, 0, lf_msg_t, 0)

typedef struct {
Reactor super;
LF_REACTION_INSTANCE(Receiver, r);
LF_PORT_INSTANCE(Receiver, in, 1);
int cnt;
LF_REACTOR_BOOKKEEPING_INSTANCES(1, 1, 0);
} Receiver;

LF_DEFINE_REACTION_BODY(Receiver, r) {
LF_SCOPE_SELF(Receiver);
LF_SCOPE_ENV();
LF_SCOPE_PORT(Receiver, in);
printf("Input triggered @ %" PRId64 " with %s size %d\n", env->get_elapsed_logical_time(env), in->value.msg,
in->value.size);
}

LF_REACTOR_CTOR_SIGNATURE_WITH_PARAMETERS(Receiver, InputExternalCtorArgs *in_external) {
LF_REACTOR_CTOR_PREAMBLE();
LF_REACTOR_CTOR(Receiver);
LF_INITIALIZE_REACTION(Receiver, r);
LF_INITIALIZE_INPUT(Receiver, in, 1, in_external);

// Register reaction as an effect of in
LF_PORT_REGISTER_EFFECT(self->in, self->r, 1);
}

LF_DEFINE_FEDERATED_INPUT_CONNECTION(Receiver, in, lf_msg_t, 5, MSEC(100), false)

typedef struct {
FederatedConnectionBundle super;
CoapUdpIpChannel channel;
LF_FEDERATED_INPUT_CONNECTION_INSTANCE(Receiver, in);
LF_FEDERATED_CONNECTION_BUNDLE_BOOKKEEPING_INSTANCES(1, 0)
} LF_FEDERATED_CONNECTION_BUNDLE_NAME(Receiver, Sender);

LF_FEDERATED_CONNECTION_BUNDLE_CTOR_SIGNATURE(Receiver, Sender) {
LF_FEDERATED_CONNECTION_BUNDLE_CTOR_PREAMBLE();
CoapUdpIpChannel_ctor(&self->channel, parent->env, REMOTE_ADDRESS, REMOTE_PROTOCOL_FAMILY);
LF_FEDERATED_CONNECTION_BUNDLE_CALL_CTOR();
LF_INITIALIZE_FEDERATED_INPUT_CONNECTION(Receiver, in, deserialize_msg_t);
}

typedef struct {
Reactor super;
LF_CHILD_REACTOR_INSTANCE(Receiver, receiver, 1);
LF_FEDERATED_CONNECTION_BUNDLE_INSTANCE(Receiver, Sender);
LF_FEDERATE_BOOKKEEPING_INSTANCES(1);
LF_CHILD_INPUT_SOURCES(receiver, in, 1, 1, 0);
} MainRecv;

LF_REACTOR_CTOR_SIGNATURE(MainRecv) {
LF_REACTOR_CTOR(MainRecv);
LF_FEDERATE_CTOR_PREAMBLE();
LF_DEFINE_CHILD_INPUT_ARGS(receiver, in, 1, 1);
LF_INITIALIZE_CHILD_REACTOR_WITH_PARAMETERS(Receiver, receiver, 1, _receiver_in_args[i]);
LF_INITIALIZE_FEDERATED_CONNECTION_BUNDLE(Receiver, Sender);
LF_BUNDLE_REGISTER_DOWNSTREAM(Receiver, Sender, receiver, in);
}

LF_ENTRY_POINT_FEDERATED(MainRecv, SEC(1), true, true, 1, false)

void print_ip_addresses(void) {
gnrc_netif_t *netif = gnrc_netif_iter(NULL);
char addr_str[IPV6_ADDR_MAX_STR_LEN];

while (netif) {
size_t max_addr_count = 4;
ipv6_addr_t addrs[max_addr_count];
gnrc_netif_ipv6_addrs_get(netif, addrs, max_addr_count * sizeof(ipv6_addr_t));

for (size_t i = 0; i < 2; i++) {
if (ipv6_addr_to_str(addr_str, &addrs[i], sizeof(addr_str))) {
LF_INFO(NET, "IPv6 address: %s", addr_str);
}
}

netif = gnrc_netif_iter(netif);
}
}

int main() {
#ifdef ONLY_PRINT_IP
print_ip_addresses();
#else
lf_start();
#endif
return 0;
}
45 changes: 45 additions & 0 deletions examples/riot/coap_federated/sender/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# name of your application
APPLICATION = lf-coap-federated-sender

# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/../../../../../RIOT

# If no BOARD is found in the environment, use this default:
BOARD ?= native

# Comment this out to disable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
DEVELHELP ?= 1

# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1

# Enable reactor-uc features
CFLAGS += -DNETWORK_CHANNEL_COAP_RIOT
REACTION_QUEUE_SIZE = 32
EVENT_QUEUE_SIZE = 32

CFLAGS += -DTHREAD_STACKSIZE_DEFAULT=10000
CFLAGS += -DTHREAD_STACKSIZE_MAIN=10000
CFLAGS += -DISR_STACKSIZE=10000

# Configure CoAP retransmission timeout
CFLAGS += -DCONFIG_GCOAP_NO_RETRANS_BACKOFF=1
CFLAGS += -DCONFIG_COAP_ACK_TIMEOUT_MS=400
CFLAGS += -DCONFIG_COAP_MAX_RETRANSMIT=4

# Check if ONLY_PRINT_IP is defined
# If ONLY_PRINT_IP is defined the REMOTE_ADDRESS is not needed
ifdef ONLY_PRINT_IP
# ONLY_PRINT_IP is defined => Set CFLAGS for it
CFLAGS += -DONLY_PRINT_IP=$(ONLY_PRINT_IP)
else ifdef REMOTE_ADDRESS
# REMOTE_ADDRESS is defined => Set CFLAGS for it
CFLAGS += -DREMOTE_ADDRESS=\"$(REMOTE_ADDRESS)\"
else
# Neither is defined
$(error Either define REMOTE_ADDRESS or set ONLY_PRINT_IP=1 to print the IP-Address of this device)
endif

include $(CURDIR)/../../../../make/riot/riot.mk
Loading

0 comments on commit b09c2ed

Please sign in to comment.