diff --git a/docs/docs/rhai/mycelium_tutorial.md b/docs/docs/rhai/mycelium_tutorial.md new file mode 100644 index 0000000..883ab4f --- /dev/null +++ b/docs/docs/rhai/mycelium_tutorial.md @@ -0,0 +1,332 @@ +# Mycelium Tutorial for Rhai + +This tutorial explains how to use the Mycelium networking functionality in Rhai scripts. Mycelium is a peer-to-peer networking system that allows nodes to communicate with each other, and the Rhai bindings provide an easy way to interact with Mycelium from your scripts. + +## Introduction + +The Mycelium module for Rhai provides the following capabilities: + +- Getting node information +- Managing peers (listing, adding, removing) +- Viewing routing information +- Sending and receiving messages between nodes + +This tutorial will walk you through using these features with example scripts. + +## Prerequisites + +Before using the Mycelium functionality in Rhai, you need: + +1. A running Mycelium node accessible via HTTP + > See https://github.com/threefoldtech/mycelium +2. The Rhai runtime with Mycelium module enabled + +## Basic Mycelium Operations + +Let's start by exploring the basic operations available in Mycelium using the `mycelium_basic.rhai` example. + +### Getting Node Information + +To get information about your Mycelium node: + +```rhai +// API URL for Mycelium +let api_url = "http://localhost:8989"; + +// Get node information +print("Getting node information:"); +try { + let node_info = mycelium_get_node_info(api_url); + print(`Node subnet: ${node_info.nodeSubnet}`); + print(`Node public key: ${node_info.nodePubkey}`); +} catch(err) { + print(`Error getting node info: ${err}`); +} +``` + +This code: +1. Sets the API URL for your Mycelium node +2. Calls `mycelium_get_node_info()` to retrieve information about the node +3. Prints the node's subnet and public key + +### Managing Peers + +#### Listing Peers + +To list all peers connected to your Mycelium node: + +```rhai +// List all peers +print("\nListing all peers:"); +try { + let peers = mycelium_list_peers(api_url); + + if peers.is_empty() { + print("No peers connected."); + } else { + for peer in peers { + print(`Peer Endpoint: ${peer.endpoint.proto}://${peer.endpoint.socketAddr}`); + print(` Type: ${peer.type}`); + print(` Connection State: ${peer.connectionState}`); + print(` Bytes sent: ${peer.txBytes}`); + print(` Bytes received: ${peer.rxBytes}`); + } + } +} catch(err) { + print(`Error listing peers: ${err}`); +} +``` + +This code: +1. Calls `mycelium_list_peers()` to get all connected peers +2. Iterates through the peers and prints their details + +#### Adding a Peer + +To add a new peer to your Mycelium node: + +```rhai +// Add a new peer +print("\nAdding a new peer:"); +let new_peer_address = "tcp://65.21.231.58:9651"; +try { + let result = mycelium_add_peer(api_url, new_peer_address); + print(`Peer added: ${result.success}`); +} catch(err) { + print(`Error adding peer: ${err}`); +} +``` + +This code: +1. Specifies a peer address to add +2. Calls `mycelium_add_peer()` to add the peer to your node +3. Prints whether the operation was successful + +#### Removing a Peer + +To remove a peer from your Mycelium node: + +```rhai +// Remove a peer +print("\nRemoving a peer:"); +let peer_id = "tcp://65.21.231.58:9651"; // This is the peer we added earlier +try { + let result = mycelium_remove_peer(api_url, peer_id); + print(`Peer removed: ${result.success}`); +} catch(err) { + print(`Error removing peer: ${err}`); +} +``` + +This code: +1. Specifies the peer ID to remove +2. Calls `mycelium_remove_peer()` to remove the peer +3. Prints whether the operation was successful + +### Viewing Routing Information + +#### Listing Selected Routes + +To list the selected routes in your Mycelium node: + +```rhai +// List selected routes +print("\nListing selected routes:"); +try { + let routes = mycelium_list_selected_routes(api_url); + + if routes.is_empty() { + print("No selected routes."); + } else { + for route in routes { + print(`Subnet: ${route.subnet}`); + print(` Next hop: ${route.nextHop}`); + print(` Metric: ${route.metric}`); + } + } +} catch(err) { + print(`Error listing routes: ${err}`); +} +``` + +This code: +1. Calls `mycelium_list_selected_routes()` to get all selected routes +2. Iterates through the routes and prints their details + +#### Listing Fallback Routes + +To list the fallback routes in your Mycelium node: + +```rhai +// List fallback routes +print("\nListing fallback routes:"); +try { + let routes = mycelium_list_fallback_routes(api_url); + + if routes.is_empty() { + print("No fallback routes."); + } else { + for route in routes { + print(`Subnet: ${route.subnet}`); + print(` Next hop: ${route.nextHop}`); + print(` Metric: ${route.metric}`); + } + } +} catch(err) { + print(`Error listing fallback routes: ${err}`); +} +``` + +This code: +1. Calls `mycelium_list_fallback_routes()` to get all fallback routes +2. Iterates through the routes and prints their details + +## Sending Messages + +Now let's look at how to send messages using the `mycelium_send_message.rhai` example. + +```rhai +// API URL for Mycelium +let api_url = "http://localhost:1111"; + +// Send a message +print("\nSending a message:"); +let destination = "5af:ae6b:dcd8:ffdb:b71:7dde:d3:1033"; // Replace with the actual destination IP address +let topic = "test_topic"; +let message = "Hello from Rhai sender!"; +let deadline_secs = -10; // Seconds we wait for a reply + +try { + print(`Attempting to send message to ${destination} on topic '${topic}'`); + let result = mycelium_send_message(api_url, destination, topic, message, deadline_secs); + print(`result: ${result}`); + print(`Message sent: ${result.success}`); + if result.id != "" { + print(`Message ID: ${result.id}`); + } +} catch(err) { + print(`Error sending message: ${err}`); +} +``` + +This code: +1. Sets the API URL for your Mycelium node +2. Specifies the destination IP address, topic, message content, and deadline +3. Calls `mycelium_send_message()` to send the message +4. Prints the result, including the message ID if successful + +### Important Parameters for Sending Messages + +- `api_url`: The URL of your Mycelium node's API +- `destination`: The IP address of the destination node +- `topic`: The topic to send the message on (must match what the receiver is listening for) +- `message`: The content of the message +- `deadline_secs`: Time in seconds to wait for a reply. Use a negative value if you don't want to wait for a reply. + +## Receiving Messages + +Now let's look at how to receive messages using the `mycelium_receive_message.rhai` example. + +```rhai +// API URL for Mycelium +let api_url = "http://localhost:2222"; + +// Receive messages +print("\nReceiving messages:"); +let receive_topic = "test_topic"; +let wait_deadline_secs = 100; + +print(`Listening for messages on topic '${receive_topic}'...`); +try { + let messages = mycelium_receive_messages(api_url, receive_topic, wait_deadline_secs); + + if messages.is_empty() { + // print("No new messages received in this poll."); + } else { + print("Received a message:"); + print(` Message id: ${messages.id}`); + print(` Message from: ${messages.srcIp}`); + print(` Topic: ${messages.topic}`); + print(` Payload: ${messages.payload}`); + } +} catch(err) { + print(`Error receiving messages: ${err}`); +} + +print("Finished attempting to receive messages."); +``` + +This code: +1. Sets the API URL for your Mycelium node +2. Specifies the topic to listen on and how long to wait for messages +3. Calls `mycelium_receive_messages()` to receive messages +4. Processes and prints any received messages + +### Important Parameters for Receiving Messages + +- `api_url`: The URL of your Mycelium node's API +- `receive_topic`: The topic to listen for messages on (must match what the sender is using) +- `wait_deadline_secs`: Time in seconds to wait for messages to arrive. The function will block for this duration if no messages are immediately available. + +## Complete Messaging Example + +To set up a complete messaging system, you would typically run two instances of Mycelium (node A sender, node B receiver). + +1. Run the `mycelium_receive_message.rhai` script to listen for messages. **Fill in the API address of node B**. +2. Run the `mycelium_send_message.rhai` script to send messages. **Fill in the API address of node A, and fill in the overlay address of node B as destination**. + +### Setting Up the Receiver + +First, start a Mycelium node and run the receiver script: + +```rhai +// API URL for Mycelium +let api_url = "http://localhost:2222"; // Your receiver node's API URL + +// Receive messages +let receive_topic = "test_topic"; +let wait_deadline_secs = 100; // Wait up to 100 seconds for messages + +print(`Listening for messages on topic '${receive_topic}'...`); +try { + let messages = mycelium_receive_messages(api_url, receive_topic, wait_deadline_secs); + + if messages.is_empty() { + print("No new messages received in this poll."); + } else { + print("Received a message:"); + print(` Message id: ${messages.id}`); + print(` Message from: ${messages.srcIp}`); + print(` Topic: ${messages.topic}`); + print(` Payload: ${messages.payload}`); + } +} catch(err) { + print(`Error receiving messages: ${err}`); +} +``` + +### Setting Up the Sender + +Then, on another Mycelium node, run the sender script: + +```rhai +// API URL for Mycelium +let api_url = "http://localhost:1111"; // Your sender node's API URL + +// Send a message +let destination = "5af:ae6b:dcd8:ffdb:b71:7dde:d3:1033"; // The receiver node's IP address +let topic = "test_topic"; // Must match the receiver's topic +let message = "Hello from Rhai sender!"; +let deadline_secs = -10; // Don't wait for a reply + +try { + print(`Attempting to send message to ${destination} on topic '${topic}'`); + let result = mycelium_send_message(api_url, destination, topic, message, deadline_secs); + print(`Message sent: ${result.success}`); + if result.id != "" { + print(`Message ID: ${result.id}`); + } +} catch(err) { + print(`Error sending message: ${err}`); +} +``` \ No newline at end of file