{"id":21281461,"url":"https://github.com/christophebedard/rmw_email","last_synced_at":"2025-04-24T03:46:19.007Z","repository":{"id":43728182,"uuid":"275610449","full_name":"christophebedard/rmw_email","owner":"christophebedard","description":"ROS 2 over email: a middleware implementation","archived":false,"fork":false,"pushed_at":"2025-03-30T21:21:38.000Z","size":92574,"stargazers_count":67,"open_issues_count":5,"forks_count":5,"subscribers_count":4,"default_branch":"rolling","last_synced_at":"2025-04-24T03:46:12.996Z","etag":null,"topics":["email","rmw","ros","ros2"],"latest_commit_sha":null,"homepage":"https://christophebedard.com/ros-2-over-email/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/christophebedard.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-28T15:12:16.000Z","updated_at":"2025-04-01T17:33:44.000Z","dependencies_parsed_at":"2025-03-29T19:19:53.928Z","dependency_job_id":"cdc2c695-c2c0-4550-b582-9ecc2d730e04","html_url":"https://github.com/christophebedard/rmw_email","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christophebedard%2Frmw_email","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christophebedard%2Frmw_email/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christophebedard%2Frmw_email/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christophebedard%2Frmw_email/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/christophebedard","download_url":"https://codeload.github.com/christophebedard/rmw_email/tar.gz/refs/heads/rolling","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250560000,"owners_count":21450168,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["email","rmw","ros","ros2"],"created_at":"2024-11-21T10:47:58.485Z","updated_at":"2025-04-24T03:46:18.992Z","avatar_url":"https://github.com/christophebedard.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rmw_email\n\n[![Latest GitHub tag](https://img.shields.io/github/v/tag/christophebedard/rmw_email?sort=semver\u0026label=version)](https://github.com/christophebedard/rmw_email/tags)\n[![GitHub workflow status](https://github.com/christophebedard/rmw_email/workflows/Test/badge.svg)](https://github.com/christophebedard/rmw_email/actions)\n[![License](https://img.shields.io/github/license/christophebedard/rmw_email)](https://github.com/christophebedard/rmw_email/blob/rolling/LICENSE)\n\nROS 2 over email.\nrmw_email contains a middleware that sends \u0026 receives strings over email and an RMW implementation that allows ROS 2 to use this middleware to exchange messages.\n\nFor an overview of the motivation and process behind this project, see this blog post: [christophebedard.com/ros-2-over-email](https://christophebedard.com/ros-2-over-email/).\n\n1. [Overview](#overview)\n1. [Packages](#packages)\n1. [Supported features](#supported-features)\n   1. [Platform support](#platform-support)\n1. [Performance](#performance)\n1. [How to use](#how-to-use)\n1. [Configuration](#configuration)\n1. [Tracing](#tracing)\n1. [Logging](#logging)\n1. [`email` examples](#email-examples)\n\n## Overview\n\n\u003cp align=\"center\"\u003e\n   \u003ca href=\"./rmw_email_cpp/img/overview_diagram.drawio\"\u003e\u003cimg src=\"./rmw_email_cpp/img/overview_diagram.png\" alt=\"overview diagram, from ROS 2 (rcl) to the email server(s) and back up to ROS 2\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n[`rmw_email_cpp`](#packages) uses [type support introspection](https://docs.ros.org/en/rolling/Concepts/About-Internal-Interfaces.html#dynamic-type-support) to convert messages to YAML objects.\nThis is done for both C and C++ type supports using the [`dynmsg` package](https://github.com/osrf/dynamic_message_introspection).\nThe YAML objects are then converted to strings.\n\nThose strings are sent via email using the [`email` package](#packages).\nThe topic name is used as the email subject; the email body contains the YAML string representing the message.\nMessages can therefore easily be read.\n\n\u003cp align=\"center\"\u003e\n   \u003ca href=\"./rmw_email_cpp/img/example_pub_sub.png\"\u003e\u003cimg src=\"./rmw_email_cpp/img/example_pub_sub.png\" alt=\"example of resulting emails after two 'hello world' messages on the '/chatter' topic\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nTo receive messages, this process is repeated in the opposite direction.\n\nSuccessive messages on the same topic generally end up in the same email thread (depending on the client).\nService responses are email replies to the corresponding email request (this is handled by `email`).\n\n\u003cp align=\"center\"\u003e\n   \u003ca href=\"./rmw_email_cpp/img/example_service.png\"\u003e\u003cimg src=\"./rmw_email_cpp/img/example_service.png\" alt=\"example of resulting emails for a service request and then response\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n`email` also has an [intraprocess communication mode](#configuration) to bypass actually sending and receiving emails.\n\n## Packages\n\nThis repository contains a few packages:\n\n* [`email`](./email/): simple publish/subscribe \u0026 service middleware using emails to exchange strings\n   * See the [API documentation](https://christophebedard.com/rmw_email/api/email/).\n   * See the [design document](./email/doc/design.md) ([rendered version](https://christophebedard.com/rmw_email/design/email/)).\n   * This package claims to be in the **Quality Level 4** category, see the [Quality Declaration](./email/QUALITY_DECLARATION.md) for more details.\n   * ![](https://img.shields.io/badge/coverage%3A%20email-%3E%2094%25-brightgreen)\n* [`email_examples`](./email_examples/): various examples using `email`\n   * See [*`email` examples*](#email-examples).\n   * This package claims to be in the **Quality Level 4** category, see the [Quality Declaration](./email_examples/QUALITY_DECLARATION.md) for more details.\n* [`rmw_email_cpp`](./rmw_email_cpp/): ROS 2 `rmw` implementation using `email` as the middleware\n   * See [*supported features*](#supported-features).\n   * This package claims to be in the **Quality Level 4** category, see the [Quality Declaration](./rmw_email_cpp/QUALITY_DECLARATION.md) for more details.\n   * ![](https://img.shields.io/badge/coverage%3A%20rmw__email__cpp-%3E%2060%25-orange)\n\n## Supported features\n\nThe following table shows the features currently supported/unsupported by `rmw_email_cpp`.\n\n| ROS 2 feature | Status |\n|---------------|--------|\n| publishers/subscriptions | :heavy_check_mark: |\n| services, actions | :heavy_check_mark: |\n| introspection using `ros2 *` commands | :x: |\n| QoS, rmw events | :x: |\n\n### Platform support\n\nrmw_email was primarily developed on Ubuntu.\nHowever, it should work on macOS and Windows without too much effort.\nSee [REP 2000](https://www.ros.org/reps/rep-2000.html#rolling-ridley-june-2020-ongoing).\n\n## Performance\n\nWe can use [performance_test](https://gitlab.com/ApexAI/performance_test) to compare the performance of `rmw_email_cpp` to another RMW implementation.\n\n\u003cp align=\"center\"\u003e\n   \u003ca href=\"./rmw_email_cpp/img/perf_comparison.png\"\u003e\u003cimg src=\"./rmw_email_cpp/img/perf_comparison.png\" alt=\"latency comparison between rmw_email_cpp and rmw_cyclonedds_cpp\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nSee the [`perf_test.sh`](./rmw_email_cpp/perf/perf_test.sh) and [`perf_plot.sh`](./rmw_email_cpp/perf/perf_plot.py) scripts to run performance_test and generate a plot like the one above.\n\n## How to use\n\n1. Clone this repo into your ROS 2 workspace\n   ```sh\n   $ cd ~/ws/src/\n   $ git clone https://github.com/christophebedard/rmw_email.git\n   ```\n1. Clone dependencies\n   ```sh\n   $ cd ~/ws/\n   $ vcs import src --input https://raw.githubusercontent.com/christophebedard/rmw_email/rolling/dependencies.repos\n   ```\n1. Build\n   ```sh\n   $ cd ~/ws/\n   $ colcon build  # ...\n   ```\n1. Create `email` configuration file(s) for your executable(s)  \n   See [*configuration*](#configuration).\n1. Use by setting the `RMW_IMPLEMENTATION` environment variable to `rmw_email_cpp` and the `EMAIL_CONFIG_FILE` environment variable to your configuration file, e.g.\n   ```sh\n   $ cd ~/ws/\n   $ source install/setup.bash\n   $ export RMW_IMPLEMENTATION=rmw_email_cpp\n   $ export EMAIL_CONFIG_FILE=path/to/email.yml\n   $ ros2 run demo_nodes_cpp talker\n   $ # ...\n   ```\n\n## Configuration\n\nIn order to send \u0026 receive emails, a YAML configuration file must be provided.\nBy default, the path to the config file is `email.yml`, relative to the current working directory.\nHowever, the path can be changed using the `EMAIL_CONFIG_FILE` environment variable, e.g., `EMAIL_CONFIG_FILE=other/dir/myemail.yml`.\nIf that file does not exist, `~/email.yml` will be used as a backup if it exists.\n\nA sample configuration file is provided: [`email.yml`](./email/email.yml).\nAs for the values:\n\n   * `url-smtp`: SMTP server URL\n      * for Gmail: `smtp.gmail.com`\n   * `url-imap`: IMAP server URL\n      * for Gmail: `imap.gmail.com`\n   * `username`: your email address\n   * `password`: your password\n      * it is recommended to generate a \"unique\" password. For Gmail, that is an [app password](https://myaccount.google.com/apppasswords). Under *Select app*, click *Other (Custom name)* and simply enter something like *rmw_email*. Copy the generated password and paste it in the config file.\n   * `to`/`cc`/`bcc`: recipients\n      * either as simple string values or as an array of string values, e.g.:\n         ```yaml\n         to: my@email.com\n         cc:\n           - some@email.com\n           - another@email.com\n         ```\n      * `to` must be defined and must contain at least one email address, but `cc` and `bcc` are optional\n   * `polling-period`: email polling period in nanoseconds\n      * optional; by default, polling will be done as fast as possible\n   * `intraprocess`: enable intraprocess mode by setting to `true`\n      * optional; by default, intraprocess is disabled\n      * this makes `email` act as if it was sending emails to itself and entirely bypasses actually sending and receiving emails\n      * all other options are optional and have no effect in practice if intraprocess is enabled\n\nUsing the same configuration file with the same email for the `username` and `to` fields (i.e., same email address for sending \u0026 receiving) for multiple executables should work.\nAlternatively, you can use two different configuration files for two different executables, e.g., if they're sending emails to each other.\n\n## Tracing\n\n`email` has LTTng tracepoints for publishers and subscriptions.\nSee [`email/include/email/lttng.hpp`](./email/include/email/lttng.hpp).\nTracepoints are automatically included if LTTng is installed and detected.\nTo completely remove them, build with `--cmake-args -DEMAIL_ENABLE_TRACING=OFF`.\n\n`rmw_email_cpp` supports the [`ros2_tracing`](https://github.com/ros2/ros2_tracing) tracepoints for the `rmw` layer.\nIt also has another LTTng tracepoint in order to link ROS 2 messages to `email` messages.\nSee [`rmw_email_cpp/include/rmw_email_cpp/lttng.hpp`](./rmw_email_cpp/include/rmw_email_cpp/lttng.hpp).\nSee [`ros2_tracing`'s README](https://github.com/ros2/ros2_tracing#building) for information on how to enable or disable tracepoints.\n\n## Logging\n\nThere are a few logging options for `email` itself:\n\n1. Set the console logging level through the `EMAIL_LOG_LEVEL` environment variable, e.g., `EMAIL_LOG_LEVEL=debug`.\n   * The logging levels are: `off`, `debug`, `info`, `warn`, `error`, and `fatal`.\n   * The default level is `info`.\n1. Write all logs to a file by setting the `EMAIL_LOG_FILE` environment variable to a file path.\n   * This writes all logs to the file, independently of the logging level set through `EMAIL_LOG_LEVEL`.\n   * A leading `~` is expanded to the user's home directory.\n1. Set the `EMAIL_CURL_VERBOSE` environment variable to be non-empty, e.g., `EMAIL_CURL_VERBOSE=y`. This will enable libcurl's verbose option.\n   * Generally produces too much output to be useful.\n\nAs for `rmw_email_cpp`, simply use the [existing logging configuration options](https://docs.ros.org/en/rolling/Tutorials/Logging-and-logger-configuration.html), including:\n\n1. [CLI option](https://docs.ros.org/en/rolling/Tutorials/Logging-and-logger-configuration.html#logger-level-configuration-command-line)\n   ```sh\n   $ ros2 run $pkg $exec --ros-args --log-level debug\n   $ ros2 run $pkg $exec --ros-args --log-level rmw_email_cpp:=debug\n   ```\n\n## `email` examples\n\nThe [`email_examples` package](./email_examples/) contains simple examples using `email`:\n\n* [email sender](./email_examples/src/send.cpp)\n* [email receiver](./email_examples/src/receive.cpp)\n* publisher\n   * [simple publisher](./email_examples/src/pub.cpp)\n* subscription\n   * [simple subscription with busy waiting](./email_examples/src/sub.cpp)\n   * [subscription using wait utilities](./email_examples/src/sub_wait.cpp)\n   * [subscription using a wait set directly](./email_examples/src/sub_wait_set.cpp)\n   * [subscription with message info](./email_examples/src/sub_wait_message_info.cpp)\n* service client\n   * [simple service client with busy waiting](./email_examples/src/service_client.cpp)\n   * [service client using wait utilities](./email_examples/src/service_client_wait.cpp)\n   * [service client with response info](./email_examples/src/service_client_wait_service_info.cpp)\n* service server\n   * [simple service server with busy waiting](./email_examples/src/service_server.cpp)\n   * [service server using wait utilities](./email_examples/src/service_server_wait.cpp)\n   * [service server with request info](./email_examples/src/service_server_wait_service_info.cpp)\n* intraprocess (meant to be used with the [intraprocess option enabled](#configuration))\n   * publisher \u0026 subscription\n      * [simple publisher with a subscription with message info in the same process](./email_examples/src/intra_pub_sub_wait_message_info.cpp)\n   * service client \u0026 service server\n      * [service client and service server with service info in the same process](./email_examples/src/intra_service_client_server_wait_service_info.cpp)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchristophebedard%2Frmw_email","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchristophebedard%2Frmw_email","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchristophebedard%2Frmw_email/lists"}