1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2026-01-01 01:41:18 +01:00

Merge pull request #21792 from LasseRosenow/doxygen-deprecate-getting-started

doc: deprecate Doxygen `Getting Started` and add CoAP guide
This commit is contained in:
Ann🐸 2025-10-15 13:45:10 +00:00 committed by GitHub
commit e46e3ac6b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 1532 additions and 76 deletions

View File

@ -38,10 +38,13 @@ parse_code_block() {
# Check if this code exists in any file in the source directory
found=0
for src_file in "$SOURCE_DIR"/*; do
# Skip if not a regular file
[ -f "$src_file" ] || continue
# Exclude `/bin/` folders
INPUT_FILES=$(
find "$SOURCE_DIR" \
-type d -name "bin" -prune\
-or -type f -print\
)
for src_file in $INPUT_FILES; do
# Read the file content
src_content=$(cat "$src_file")

View File

@ -1,6 +1,9 @@
Getting started {#getting-started}
Getting started (Deprecated) {#getting-started}
===============
@deprecated Guides have moved to the [Guide Site](https://guide.riot-os.org/getting-started/installing/).
This page will be removed after release 2026.04.
[TOC]
@deprecated See [Setup Guide](https://guide.riot-os.org/getting-started/installing/#architecture-specific-requirements) on the RIOT Guide Site for the latest information. This section will be removed after release 2025.11.
@ -17,28 +20,11 @@ Building and executing an example {#building-and-executing-an-example}
Configuring an application {#configuring-an-application}
--------------------------
Many modules in RIOT offer configuration options that will be considered during
compile-time.They are modeled as macros that can be overridden by the user.
Currently there are two ways of doing this: using `CFLAGS` or via
@ref kconfig-in-riot "Kconfig" (the last one is currently only possible for a
subset of modules).
For instructions on how to configure via `CFLAGS` check the
@ref config "identified compile-time configurations". To learn how to use
Kconfig in RIOT, please refer to the
[User's guide to configure with Kconfig](https://guide.riot-os.org/build-system/kconfig/#configure-using-menuconfig).
@deprecated See [Configuring an Application](https://guide.riot-os.org/advanced_tutorials/creating_application/#configuring-an-application) on the RIOT Guide Site for the latest information. This section will be removed after release 2026.04.
Default configurations {#default-configurations}
----------------------
When devices have a common access interface, having a default configuration to
enable them across platforms, without having to explicitly specify which modules
to include, comes in handy. For this, two pseudomodules are defined:
- `saul_default`: will enable all the drivers of sensors and actuators that are
present in the target platform.
- `netdev_default`: will enable all the drivers of network devices
present in the target platform.
@deprecated See [Default Configurations](https://guide.riot-os.org/advanced_tutorials/creating_application/#default-configurations) on the RIOT Guide Site for the latest information. This section will be removed after release 2026.04.
Use Docker to build RIOT {#docker}
========================
@ -48,37 +34,9 @@ Use Docker to build RIOT {#docker}
Generating compile_commands.json e.g. for code completion in IDEs
=================================================================
See [Setup Guide](https://guide.riot-os.org/getting-started/installing/#using-vs-code-for-development) for a guide on how to set up VS Code for RIOT development using the `compile_commands.json` file.
This target will honor the variables controlling the build process such as `BOARD`, `TOOLCHAIN`,
`DEVELHELP`, etc. just like the usual build process. This works without actual compilation. By
default, the `compile_commands.json` is placed in the RIOT base directory. This behavior can be
overwritten using the `COMPILE_COMMANDS_PATH` variable by specifying the full absolute path
(including file name) of the `compile_commands.json` instead.
***Note:*** By default, the built-in include search directories of GCC will be explicitly added
and flags incompatible with `clangd` will be dropped. This will allow using `clangd` as language
server out of the box. If this is not desired, run `export COMPILE_COMMANDS_FLAGS=""` to turn
modification of the compile commands off. For a list of available flags, run
`./dist/tools/compile_commands/compile_commands.py --help` in the RIOT base directory.
@deprecated See [Generating compile_commands.json](https://guide.riot-os.org/getting-started/installing/#generating-compile_commandsjson-eg-for-code-completion-in-ides) on the RIOT Guide Site for the latest information. This section will be removed after release 2026.04.
Using the native port with networking
=====================================
If you compile RIOT for the native cpu and include the `netdev_tap` module,
you can specify a network interface like this: `PORT=tap0 make term`
Setting up a tap network
------------------------
There is a shell script in `RIOT/dist/tools/tapsetup` called `tapsetup` which
you can use to create a network of tap interfaces.
*USAGE*
To create a bridge and two (or `count` at your option) tap interfaces:
~~~~~~~{.sh}
sudo ./dist/tools/tapsetup/tapsetup [-c [<count>]]
~~~~~~~
A detailed example can be found in `examples/networking/gnrc/gnrc_networking`.
@deprecated See [Networking](https://guide.riot-os.org/c_tutorials/networking/) on the RIOT Guide Site for the latest information. This section will be removed after release 2026.04.

View File

@ -95,6 +95,60 @@ USEMODULE += gnrc_udp
Modules typically pull in all required dependencies themselves.
### Configuring an Application
Many modules in RIOT offer configuration options that will be considered during
compile-time. They are modeled as macros that can be overridden by the user.
Currently there are three ways of doing this: Using `CFLAGS`, `pseudomodules`
and [Kconfig](https://guide.riot-os.org/build-system/kconfig) (the last one is
currently only possible for a subset of modules).
#### CFLAGS
`CFLAGS` can be set in your `Makefile` to configure the values of `defines`.
Make sure to not override the `CFLAGS` variable and only extend it using
the `+=` operator.
For example, to increase the stack size of the main thread,
your Makefile needs to contain this line:
```makefile
CFLAGS += -DTHREAD_STACKSIZE_MAIN=2048
```
For a list of all compile time configurations check the
[API Documentation](https://doc.riot-os.org/group__config.html).
#### Kconfig
To learn how to use [Kconfig](https://guide.riot-os.org/build-system/kconfig)
in RIOT, please refer to the
[User Guide to Configure with Kconfig](https://guide.riot-os.org/build-system/kconfig/#user-guide-to-configure-with-kconfig).
#### Pseudomodules
When devices have a common access interface, having a default configuration to
enable them across platforms, without having to explicitly specify which modules
to include, comes in handy. For this, `pseudomodules` are defined:
##### SAUL Default
Will enable all the drivers of sensors and actuators that are
present in the target platform.
```makefile
USEMODULE += saul_default
```
##### Netdev Default
Will enable all the drivers of network devices
present in the target platform.
```makefile
USEMODULE += netdev_default
```
## Including Source Files in Subfolders
By default, all source files in an application's (or any RIOT module's) directory

View File

@ -0,0 +1,373 @@
---
title: CoAP Networking
description: Learn how to use CoAP with RIOT
code_folder: examples/guides/coap
---
CoAP (Constrained Application Protocol) is a protocol to implement REST APIs
for constrained devices and networks.
It is designed for IoT applications and is similar to HTTP but much lighter.
This guide walks you through creating a simple CoAP
application using RIOT's gcoap module. You will build both a server that responds
to requests and a client that sends requests, demonstrating basic CoAP communication.
:::note
This tutorial explains how to use `gcoap`, RIOT's CoAP implementation.
Note that we are currently developing `unicoap`, a new CoAP implementation
that will feature a more streamlined API and additional functionality.
:::
## Creating the CoAP Server
### Step 1: Project Structure
Create a new directory for your project:
```text
coap-hello-server
├── Makefile
└── main.c
```
### Step 2: Create the Makefile
For CoAP support we need to include the `gcoap` module.
For the IPv6 network stack we include the `gnrc_ipv6_default` module.
To initialize the network device we include the `netdev_default` module.
And to easily find our server from the client we set the static local
IPv6 address to `fe80::cafe:cafe:cafe:1`.
```makefile title=Makefile {9-22}
APPLICATION = coap_hello_server
# Board selection - change this to your target board
BOARD ?= native
# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/../RIOT
# Include packages that pull up and auto-init the link layer
USEMODULE += netdev_default
USEMODULE += auto_init_gnrc_netif
# Network stack
USEMODULE += gnrc_ipv6_default
USEMODULE += gnrc_icmpv6_echo
# Include gcoap module
USEMODULE += gcoap
# Static local IPv6 address
CFLAGS += -DCONFIG_GNRC_IPV6_STATIC_LLADDR='"fe80::cafe:cafe:cafe:1"'
CFLAGS += -DCONFIG_GNRC_IPV6_STATIC_LLADDR_IS_FIXED=1
include $(RIOTBASE)/Makefile.include
```
### Step 3: Implement the CoAP Server
```c title=main.c
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "net/gcoap.h"
/* Response message */
static const char RESPONSE_MSG[] = "World";
/* CoAP resource handler for /hello */
static ssize_t _hello_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len,
coap_request_ctx_t *ctx)
{
(void)ctx; /* unused parameter */
gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT);
/* Set content format to plain text */
coap_opt_add_format(pdu, COAP_FORMAT_TEXT);
/* Finalize options and get payload pointer */
size_t resp_len = coap_opt_finish(pdu, COAP_OPT_FINISH_PAYLOAD);
/* Add the response message */
if (pdu->payload_len >= sizeof(RESPONSE_MSG)) {
memcpy(pdu->payload, RESPONSE_MSG, sizeof(RESPONSE_MSG) - 1);
resp_len += sizeof(RESPONSE_MSG) - 1;
}
else {
puts("gcoap: msg buffer too small");
return gcoap_response(pdu, buf, len, COAP_CODE_INTERNAL_SERVER_ERROR);
}
return resp_len;
}
/* CoAP resources array */
static const coap_resource_t _resources[] = {
{ "/hello", COAP_GET, _hello_handler, NULL },
};
/* gcoap listener structure */
static gcoap_listener_t _listener = {
&_resources[0],
ARRAY_SIZE(_resources),
GCOAP_SOCKET_TYPE_UDP,
NULL,
NULL,
NULL
};
int main(void)
{
/* Initialize CoAP server */
gcoap_register_listener(&_listener);
puts("CoAP server initialized");
puts("Listening on /hello");
return 0;
}
```
### Step 5: Build and Run the Server
Run the following command from the terminal:
```bash
make all term
```
Or run the following command to flash it to a board:
```bash
BOARD=arduino-feather-nrf52840-sense make all flash term
```
## Creating the CoAP Client
### Step 1: Project Structure
Create a new directory for your project:
```text
coap-hello-client
├── Makefile
└── main.c
```
### Step 2: Create the Makefile
```makefile title=Makefile {7-23}
APPLICATION = coap_hello_client
BOARD ?= native
RIOTBASE ?= $(CURDIR)/../RIOT
# Include packages that pull up and auto-init the link layer
USEMODULE += netdev_default
USEMODULE += auto_init_gnrc_netif
# Network stack
USEMODULE += gnrc_ipv6_default
USEMODULE += gnrc_icmpv6_echo
# Include gcoap module
USEMODULE += gcoap
# Include shell for interactive commands
USEMODULE += shell
USEMODULE += shell_cmds_default
# CoAP Server Address
CFLAGS += -DSERVER_ADDRESS='"fe80::cafe:cafe:cafe:1"'
include $(RIOTBASE)/Makefile.include
```
### Step 3: Implement the CoAP Client
```c title=main.c
#include <stdio.h>
#include <string.h>
#include "net/gcoap.h"
#include "net/ipv6/addr.h"
#include "shell.h"
#include "msg.h"
#define MAIN_QUEUE_SIZE (8)
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
/* Buffer for the request */
static uint8_t buf[CONFIG_GCOAP_PDU_BUF_SIZE];
/* Response handler callback */
static void _resp_handler(const gcoap_request_memo_t *memo, coap_pkt_t *pdu,
const sock_udp_ep_t *remote)
{
(void)remote;
if (memo->state == GCOAP_MEMO_TIMEOUT) {
puts("Request timed out");
return;
}
else if (memo->state == GCOAP_MEMO_RESP) {
char *class_str = (coap_get_code_class(pdu) == COAP_CLASS_SUCCESS) ?
"Success" :
"Error";
printf("Response: %s (Code: %u.%02u)\n", class_str,
coap_get_code_class(pdu), coap_get_code_detail(pdu));
/* Print payload if present */
if (pdu->payload_len) {
printf("Payload: %.*s\n", pdu->payload_len, (char *)pdu->payload);
}
}
}
/* Send CoAP GET request to /hello endpoint */
static int _send_coap_request(void)
{
sock_udp_ep_t remote;
coap_pkt_t pdu;
size_t len;
/* Parse IPv6 address */
remote.family = AF_INET6;
remote.netif = SOCK_ADDR_ANY_NETIF;
remote.port = CONFIG_GCOAP_PORT;
if (ipv6_addr_from_str((ipv6_addr_t *)&remote.addr.ipv6, SERVER_ADDRESS) ==
NULL) {
puts("Error: unable to parse destination address");
return -1;
}
/* Initialize CoAP request */
len = gcoap_req_init(&pdu, buf, CONFIG_GCOAP_PDU_BUF_SIZE, COAP_METHOD_GET,
"/hello");
/* Set content format option */
coap_opt_add_format(&pdu, COAP_FORMAT_TEXT);
/* Finish options */
len = coap_opt_finish(&pdu, COAP_OPT_FINISH_NONE);
/* Send request */
ssize_t res = gcoap_req_send(buf, len, &remote, NULL, _resp_handler, NULL,
GCOAP_SOCKET_TYPE_UDP);
if (res <= 0) {
puts("Error sending request");
return -1;
}
printf("Request sent (%d bytes)\n", (int)res);
return 0;
}
/* Shell command to send CoAP request */
static int _shell_command_hello(int argc, char **argv)
{
(void)argc;
(void)argv;
return _send_coap_request();
}
SHELL_COMMAND(hello, "Send CoAP request to /hello endpoint",
_shell_command_hello);
int main(void)
{
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
puts("RIOT CoAP Hello Client");
puts("Use 'hello' to send CoAP requests");
char buffer[SHELL_DEFAULT_BUFSIZE];
shell_run(NULL, buffer, SHELL_DEFAULT_BUFSIZE);
return 0;
}
```
### Step 4: Build and Run the Client
Run the following command from the terminal:
```bash
make all term
```
Or run the following command to flash it to a board:
```bash
BOARD=arduino-feather-nrf52840-sense make all flash term
```
## Testing Both Together
### Using a Board
When flashing to a board you must first make sure that the network stack is correctly configured.
Then run the following shell command after flashing and connecting to the shell of the
CoAP client board:
```bash
coap_get fe80::cafe:cafe:cafe:1 /hello
```
You should see:
```text
Request sent (XX bytes)
Response: Success (Code: 2.05)
Payload: World
```
### Using Native (TAP) Network
#### Step 1: Create the TAP Bridge on the Linux Host
From the root of the RIOT source directory run the following command:
```shell
sudo ./dist/tools/tapsetup/tapsetup -c 2
```
#### Step 2: Flash and Run the Server
Run the following command to build, flash and run the CoAP server:
```bash
cd coap-hello-server
make BOARD=native PORT=tap0 all term
```
#### Step 3: Flash and Run the Client
Now run the following command in a separate window:
```bash
cd coap-hello-client
make BOARD=native PORT=tap1 all term
```
Now from the RIOT shell run the following command:
```bash
coap_get fe80::cafe:cafe:cafe:1 /hello
```
You should see:
```text
Request sent (XX bytes)
Response: Success (Code: 2.05)
Payload: World
```

View File

@ -58,9 +58,11 @@ the following line, logging out and logging in again:
sudo usermod -aG $(stat --format="%G" /dev/ttyACM0) $USER
```
Note that the `PORT` macro has a slightly different semantic in `native`. Here
:::note
The `PORT` macro has a slightly different semantic in `native`. Here
it is used to provide the name of the TAP interface you want to use for the
virtualized networking capabilities of RIOT.
:::
We use `pyterm` as the default terminal application. It is shipped with RIOT in
the `dist/tools/pyterm/` directory. If you choose to use another terminal
@ -80,22 +82,3 @@ main(): This is RIOT!
```
when you flash the board. In this case, type `reboot` in the command line or reboot manually.
:::tip[Using the native port with networking]
If you compile RIOT for the native cpu and include the `netdev_tap` module,
you can specify a network interface like this: `PORT=tap0 make term`
*Setting up a tap network*
There is a shell script in `RIOT/dist/tools/tapsetup` called `tapsetup` which
you can use to create a network of tap interfaces.
*USAGE*
To create a bridge and two (or `count` at your option) tap interfaces:
```shell
sudo ./dist/tools/tapsetup/tapsetup [-c [<count>]]
```
A detailed example can be found in `examples/networking/gnrc/gnrc_networking`.
:::

View File

@ -107,6 +107,22 @@ The app should behave the same when run on real hardware.
2. With the `Ctrl`-key still held, press the `C`-key
3. Release both keys
## Generating compile_commands.json e.g. for Code Completion in IDEs
This target will honor the variables controlling the build process such as `BOARD`, `TOOLCHAIN`,
`DEVELHELP`, etc. just like the usual build process. This works without actual compilation. By
default, the `compile_commands.json` is placed in the RIOT base directory. This behavior can be
overwritten using the `COMPILE_COMMANDS_PATH` variable by specifying the full absolute path
(including file name) of the `compile_commands.json` instead.
:::note
By default, the built-in include search directories of GCC will be explicitly added
and flags incompatible with `clangd` will be dropped. This will allow using `clangd` as language
server out of the box. If this is not desired, run `export COMPILE_COMMANDS_FLAGS=""` to turn
modification of the compile commands off. For a list of available flags, run
`./dist/tools/compile_commands/compile_commands.py --help` in the RIOT base directory.
:::
## Using VS Code for Development
- If not already open, open the terminal
@ -116,7 +132,7 @@ The app should behave the same when run on real hardware.
- If the blue string is not `~/RIOT/examples/basic/hello-world`, type
`cd ~/RIOT/examples/basic/hello-world` to enter that path
- Inside `~/RIOT/examples/basic/hello-world` run the command `make compile-commands`
- The output should look like above
- The output should look like below
![Ubuntu terminal running `make compile-commands` in the `hello-world` app](img/06-Use_VS_Code-01.png)

View File

@ -5,7 +5,7 @@ RIOTTOOLS ?= $(RIOTBASE)/dist/tools
.PHONY: install
install: integrate_outside_files
@echo "Installing starlight..."
@npm install --prefix $(CURDIR) --prefer-offline
@npm ci --prefix $(CURDIR) --prefer-offline
@echo "Starlight installed successfully."
.PHONY: build

View File

@ -112,6 +112,7 @@ export default defineConfig({
"c_tutorials/threads",
"c_tutorials/gpio",
"c_tutorials/saul",
"c_tutorials/coap",
"c_tutorials/coding_conventions",
],
},

View File

@ -122,6 +122,7 @@
"resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.36.0.tgz",
"integrity": "sha512-aVJVBfvFuE2avsMDhmRzn6I5GjDhUwIQFlu3qH9a1C0fNsPYDw2asxHQODAD7EfGiKGvvHCJgHb+9jbJ8lCfNQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@astrojs/markdown-remark": "^6.3.1",
"@astrojs/mdx": "^4.2.3",
@ -258,6 +259,262 @@
"tslib": "^2.4.0"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz",
"integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==",
"cpu": [
"ppc64"
],
"license": "MIT",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz",
"integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz",
"integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz",
"integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz",
"integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz",
"integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz",
"integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz",
"integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz",
"integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz",
"integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz",
"integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==",
"cpu": [
"ia32"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz",
"integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==",
"cpu": [
"loong64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz",
"integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==",
"cpu": [
"mips64el"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz",
"integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==",
"cpu": [
"ppc64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz",
"integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==",
"cpu": [
"riscv64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz",
"integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==",
"cpu": [
"s390x"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz",
@ -274,6 +531,150 @@
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz",
"integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz",
"integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz",
"integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz",
"integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openharmony-arm64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz",
"integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"openharmony"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz",
"integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz",
"integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz",
"integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==",
"cpu": [
"ia32"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.25.10",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz",
"integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@expressive-code/core": {
"version": "0.41.3",
"resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.41.3.tgz",
@ -795,12 +1196,64 @@
"integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==",
"license": "MIT"
},
"node_modules/@pagefind/darwin-arm64": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.4.0.tgz",
"integrity": "sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@pagefind/darwin-x64": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.4.0.tgz",
"integrity": "sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@pagefind/default-ui": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@pagefind/default-ui/-/default-ui-1.4.0.tgz",
"integrity": "sha512-wie82VWn3cnGEdIjh4YwNESyS1G6vRHwL6cNjy9CFgNnWW/PGRjsLq300xjVH5sfPFK3iK36UxvIBymtQIEiSQ==",
"license": "MIT"
},
"node_modules/@pagefind/freebsd-x64": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@pagefind/freebsd-x64/-/freebsd-x64-1.4.0.tgz",
"integrity": "sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/@pagefind/linux-arm64": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.4.0.tgz",
"integrity": "sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@pagefind/linux-x64": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.4.0.tgz",
@ -814,6 +1267,19 @@
"linux"
]
},
"node_modules/@pagefind/windows-x64": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.4.0.tgz",
"integrity": "sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/pluginutils": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz",
@ -842,6 +1308,201 @@
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"license": "MIT"
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.2.tgz",
"integrity": "sha512-o3pcKzJgSGt4d74lSZ+OCnHwkKBeAbFDmbEm5gg70eA8VkyCuC/zV9TwBnmw6VjDlRdF4Pshfb+WE9E6XY1PoQ==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.2.tgz",
"integrity": "sha512-cqFSWO5tX2vhC9hJTK8WAiPIm4Q8q/cU8j2HQA0L3E1uXvBYbOZMhE2oFL8n2pKB5sOCHY6bBuHaRwG7TkfJyw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.2.tgz",
"integrity": "sha512-vngduywkkv8Fkh3wIZf5nFPXzWsNsVu1kvtLETWxTFf/5opZmflgVSeLgdHR56RQh71xhPhWoOkEBvbehwTlVA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.2.tgz",
"integrity": "sha512-h11KikYrUCYTrDj6h939hhMNlqU2fo/X4NB0OZcys3fya49o1hmFaczAiJWVAFgrM1NCP6RrO7lQKeVYSKBPSQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.2.tgz",
"integrity": "sha512-/eg4CI61ZUkLXxMHyVlmlGrSQZ34xqWlZNW43IAU4RmdzWEx0mQJ2mN/Cx4IHLVZFL6UBGAh+/GXhgvGb+nVxw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.2.tgz",
"integrity": "sha512-QOWgFH5X9+p+S1NAfOqc0z8qEpJIoUHf7OWjNUGOeW18Mx22lAUOiA9b6r2/vpzLdfxi/f+VWsYjUOMCcYh0Ng==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.2.tgz",
"integrity": "sha512-kDWSPafToDd8LcBYd1t5jw7bD5Ojcu12S3uT372e5HKPzQt532vW+rGFFOaiR0opxePyUkHrwz8iWYEyH1IIQA==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.2.tgz",
"integrity": "sha512-gKm7Mk9wCv6/rkzwCiUC4KnevYhlf8ztBrDRT9g/u//1fZLapSRc+eDZj2Eu2wpJ+0RzUKgtNijnVIB4ZxyL+w==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.2.tgz",
"integrity": "sha512-66lA8vnj5mB/rtDNwPgrrKUOtCLVQypkyDa2gMfOefXK6rcZAxKLO9Fy3GkW8VkPnENv9hBkNOFfGLf6rNKGUg==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.2.tgz",
"integrity": "sha512-s+OPucLNdJHvuZHuIz2WwncJ+SfWHFEmlC5nKMUgAelUeBUnlB4wt7rXWiyG4Zn07uY2Dd+SGyVa9oyLkVGOjA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-loong64-gnu": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.2.tgz",
"integrity": "sha512-8wTRM3+gVMDLLDdaT6tKmOE3lJyRy9NpJUS/ZRWmLCmOPIJhVyXwjBo+XbrrwtV33Em1/eCTd5TuGJm4+DmYjw==",
"cpu": [
"loong64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.2.tgz",
"integrity": "sha512-6yqEfgJ1anIeuP2P/zhtfBlDpXUb80t8DpbYwXQ3bQd95JMvUaqiX+fKqYqUwZXqdJDd8xdilNtsHM2N0cFm6A==",
"cpu": [
"ppc64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.2.tgz",
"integrity": "sha512-sshYUiYVSEI2B6dp4jMncwxbrUqRdNApF2c3bhtLAU0qA8Lrri0p0NauOsTWh3yCCCDyBOjESHMExonp7Nzc0w==",
"cpu": [
"riscv64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-riscv64-musl": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.2.tgz",
"integrity": "sha512-duBLgd+3pqC4MMwBrKkFxaZerUxZcYApQVC5SdbF5/e/589GwVvlRUnyqMFbM8iUSb1BaoX/3fRL7hB9m2Pj8Q==",
"cpu": [
"riscv64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.2.tgz",
"integrity": "sha512-tzhYJJidDUVGMgVyE+PmxENPHlvvqm1KILjjZhB8/xHYqAGeizh3GBGf9u6WdJpZrz1aCpIIHG0LgJgH9rVjHQ==",
"cpu": [
"s390x"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.2.tgz",
@ -868,6 +1529,71 @@
"linux"
]
},
"node_modules/@rollup/rollup-openharmony-arm64": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.2.tgz",
"integrity": "sha512-uPj7MQ6/s+/GOpolavm6BPo+6CbhbKYyZHUDvZ/SmJM7pfDBgdGisFX3bY/CBDMg2ZO4utfhlApkSfZ92yXw7Q==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"openharmony"
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.2.tgz",
"integrity": "sha512-Z9MUCrSgIaUeeHAiNkm3cQyst2UhzjPraR3gYYfOjAuZI7tcFRTOD+4cHLPoS/3qinchth+V56vtqz1Tv+6KPA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.2.tgz",
"integrity": "sha512-+GnYBmpjldD3XQd+HMejo+0gJGwYIOfFeoBQv32xF/RUIvccUz20/V6Otdv+57NE70D5pa8W/jVGDoGq0oON4A==",
"cpu": [
"ia32"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-x64-gnu": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.2.tgz",
"integrity": "sha512-ApXFKluSB6kDQkAqZOKXBjiaqdF1BlKi+/eqnYe9Ee7U2K3pUDKsIyr8EYm/QDHTJIM+4X+lI0gJc3TTRhd+dA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.52.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.2.tgz",
"integrity": "sha512-ARz+Bs8kY6FtitYM96PqPEVvPXqEZmPZsSkXvyX19YzDqkCaIlhCieLLMI5hxO9SRZ2XtCtm8wxhy0iJ2jxNfw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@shikijs/core": {
"version": "3.13.0",
"resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.13.0.tgz",
@ -1057,6 +1783,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@ -1217,6 +1944,7 @@
"resolved": "https://registry.npmjs.org/astro/-/astro-5.14.1.tgz",
"integrity": "sha512-gPa8NY7/lP8j8g81iy8UwANF3+aukKRWS68IlthZQNgykpg80ne6lbHOp6FErYycxQ1TUhgEfkXVDQZAoJx8Bg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@astrojs/compiler": "^2.12.2",
"@astrojs/internal-helpers": "0.7.3",
@ -2105,6 +2833,20 @@
"unicode-trie": "^2.0.0"
}
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/gemoji": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/gemoji/-/gemoji-8.1.0.tgz",
@ -4193,6 +4935,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@ -4690,6 +5433,7 @@
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.2.tgz",
"integrity": "sha512-I25/2QgoROE1vYV+NQ1En9T9UFB9Cmfm2CJ83zZOlaDpvz29wGQSZXWKw7MiNXau7wYgB/T9fVIdIuEQ+KbiiA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@types/estree": "1.0.8"
},
@ -5438,6 +6182,7 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.6.tgz",
"integrity": "sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==",
"license": "MIT",
"peer": true,
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.4.4",
@ -5652,6 +6397,7 @@
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
"license": "MIT",
"peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}

View File

@ -0,0 +1 @@
../creating_project/README.md

View File

@ -0,0 +1,39 @@
# Name of your application
APPLICATION = coap_hello_client
# Change this to your board if you want to build for a different board
BOARD ?= native
# This has to be the absolute path to the RIOT base directory:
# If you are following the tutorial, your RIOT base directory will
# most likely be something like RIOTBASE ?= $(CURDIR)/RIOT
# instead of this
RIOTBASE ?= $(CURDIR)/../../../..
# 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
# Include packages that pull up and auto-init the link layer
USEMODULE += netdev_default
USEMODULE += auto_init_gnrc_netif
# Network stack
USEMODULE += gnrc_ipv6_default
USEMODULE += gnrc_icmpv6_echo
# Include gcoap module
USEMODULE += gcoap
# Include shell for interactive commands
USEMODULE += shell
USEMODULE += shell_cmds_default
# CoAP Server Address
CFLAGS += -DSERVER_ADDRESS='"fe80::cafe:cafe:cafe:1"'
# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,35 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
atmega8 \
bluepill-stm32f030c8 \
i-nucleo-lrwan1 \
msb-430 \
msb-430h \
nucleo-c031c6 \
nucleo-f030r8 \
nucleo-f031k6 \
nucleo-f042k6 \
nucleo-f303k8 \
nucleo-f334r8 \
nucleo-l011k4 \
nucleo-l031k6 \
nucleo-l053r8 \
olimex-msp430-h1611 \
olimex-msp430-h2618 \
samd10-xmini \
slstk3400a \
stk3200 \
stm32f030f4-demo \
stm32f0discovery \
stm32g0316-disco \
stm32l0538-disco \
telosb \
weact-g030f6 \
z1 \
#

View File

@ -0,0 +1,109 @@
/*
* SPDX-FileCopyrightText: 2025 Lasse Rosenow
* SPDX-FileCopyrightText: 2025 HAW Hamburg
* SPDX-License-Identifier: LGPL-2.1-only
*/
#include <stdio.h>
#include <string.h>
#include "net/gcoap.h"
#include "net/ipv6/addr.h"
#include "shell.h"
#include "msg.h"
#define MAIN_QUEUE_SIZE (8)
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
/* Buffer for the request */
static uint8_t buf[CONFIG_GCOAP_PDU_BUF_SIZE];
/* Response handler callback */
static void _resp_handler(const gcoap_request_memo_t *memo, coap_pkt_t *pdu,
const sock_udp_ep_t *remote)
{
(void)remote;
if (memo->state == GCOAP_MEMO_TIMEOUT) {
puts("Request timed out");
return;
}
else if (memo->state == GCOAP_MEMO_RESP) {
char *class_str = (coap_get_code_class(pdu) == COAP_CLASS_SUCCESS) ?
"Success" :
"Error";
printf("Response: %s (Code: %u.%02u)\n", class_str,
coap_get_code_class(pdu), coap_get_code_detail(pdu));
/* Print payload if present */
if (pdu->payload_len) {
printf("Payload: %.*s\n", pdu->payload_len, (char *)pdu->payload);
}
}
}
/* Send CoAP GET request to /hello endpoint */
static int _send_coap_request(void)
{
sock_udp_ep_t remote;
coap_pkt_t pdu;
size_t len;
/* Parse IPv6 address */
remote.family = AF_INET6;
remote.netif = SOCK_ADDR_ANY_NETIF;
remote.port = CONFIG_GCOAP_PORT;
if (ipv6_addr_from_str((ipv6_addr_t *)&remote.addr.ipv6, SERVER_ADDRESS) ==
NULL) {
puts("Error: unable to parse destination address");
return -1;
}
/* Initialize CoAP request */
len = gcoap_req_init(&pdu, buf, CONFIG_GCOAP_PDU_BUF_SIZE, COAP_METHOD_GET,
"/hello");
/* Set content format option */
coap_opt_add_format(&pdu, COAP_FORMAT_TEXT);
/* Finish options */
len = coap_opt_finish(&pdu, COAP_OPT_FINISH_NONE);
/* Send request */
ssize_t res = gcoap_req_send(buf, len, &remote, NULL, _resp_handler, NULL,
GCOAP_SOCKET_TYPE_UDP);
if (res <= 0) {
puts("Error sending request");
return -1;
}
printf("Request sent (%d bytes)\n", (int)res);
return 0;
}
/* Shell command to send CoAP request */
static int _shell_command_hello(int argc, char **argv)
{
(void)argc;
(void)argv;
return _send_coap_request();
}
SHELL_COMMAND(hello, "Send CoAP request to /hello endpoint",
_shell_command_hello);
int main(void)
{
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
puts("RIOT CoAP Hello Client");
puts("Use 'hello' to send CoAP requests");
char buffer[SHELL_DEFAULT_BUFSIZE];
shell_run(NULL, buffer, SHELL_DEFAULT_BUFSIZE);
return 0;
}

View File

@ -0,0 +1,36 @@
# Name of your application
APPLICATION = coap_hello_server
# Change this to your board if you want to build for a different board
BOARD ?= native
# This has to be the absolute path to the RIOT base directory:
# If you are following the tutorial, your RIOT base directory will
# most likely be something like RIOTBASE ?= $(CURDIR)/RIOT
# instead of this
RIOTBASE ?= $(CURDIR)/../../../..
# 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
# Include packages that pull up and auto-init the link layer
USEMODULE += netdev_default
USEMODULE += auto_init_gnrc_netif
# Network stack
USEMODULE += gnrc_ipv6_default
USEMODULE += gnrc_icmpv6_echo
# Include gcoap module
USEMODULE += gcoap
# Static local IPv6 address
CFLAGS += -DCONFIG_GNRC_IPV6_STATIC_LLADDR='"fe80::cafe:cafe:cafe:1"'
CFLAGS += -DCONFIG_GNRC_IPV6_STATIC_LLADDR_IS_FIXED=1
# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,34 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
atmega8 \
bluepill-stm32f030c8 \
i-nucleo-lrwan1 \
msb-430 \
msb-430h \
nucleo-c031c6 \
nucleo-f030r8 \
nucleo-f031k6 \
nucleo-f042k6 \
nucleo-f303k8 \
nucleo-f334r8 \
nucleo-l011k4 \
nucleo-l031k6 \
nucleo-l053r8 \
olimex-msp430-h1611 \
samd10-xmini \
slstk3400a \
stk3200 \
stm32f030f4-demo \
stm32f0discovery \
stm32g0316-disco \
stm32l0538-disco \
telosb \
weact-g030f6 \
z1 \
#

View File

@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: 2025 Lasse Rosenow
* SPDX-FileCopyrightText: 2025 HAW Hamburg
* SPDX-License-Identifier: LGPL-2.1-only
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "net/gcoap.h"
/* Response message */
static const char RESPONSE_MSG[] = "World";
/* CoAP resource handler for /hello */
static ssize_t _hello_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len,
coap_request_ctx_t *ctx)
{
(void)ctx; /* unused parameter */
gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT);
/* Set content format to plain text */
coap_opt_add_format(pdu, COAP_FORMAT_TEXT);
/* Finalize options and get payload pointer */
size_t resp_len = coap_opt_finish(pdu, COAP_OPT_FINISH_PAYLOAD);
/* Add the response message */
if (pdu->payload_len >= sizeof(RESPONSE_MSG)) {
memcpy(pdu->payload, RESPONSE_MSG, sizeof(RESPONSE_MSG) - 1);
resp_len += sizeof(RESPONSE_MSG) - 1;
}
else {
puts("gcoap: msg buffer too small");
return gcoap_response(pdu, buf, len, COAP_CODE_INTERNAL_SERVER_ERROR);
}
return resp_len;
}
/* CoAP resources array */
static const coap_resource_t _resources[] = {
{ "/hello", COAP_GET, _hello_handler, NULL },
};
/* gcoap listener structure */
static gcoap_listener_t _listener = {
&_resources[0],
ARRAY_SIZE(_resources),
GCOAP_SOCKET_TYPE_UDP,
NULL,
NULL,
NULL
};
int main(void)
{
/* Initialize CoAP server */
gcoap_register_listener(&_listener);
puts("CoAP server initialized");
puts("Listening on /hello");
return 0;
}