{"id":17873783,"url":"https://github.com/boshtannik/embedded-nano-mesh","last_synced_at":"2025-03-21T21:31:53.572Z","repository":{"id":187736774,"uuid":"677472852","full_name":"boshtannik/embedded-nano-mesh","owner":"boshtannik","description":"The repo of mesh networking for small-memory embedded devices","archived":false,"fork":false,"pushed_at":"2024-10-12T22:05:18.000Z","size":329,"stargazers_count":7,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-28T12:28:10.053Z","etag":null,"topics":["embedded","iot","mesh","networking","protocol","rust-lang"],"latest_commit_sha":null,"homepage":"","language":"Rust","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/boshtannik.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.txt","contributing":null,"funding":".github/funding.yml","license":"LICENSE-APACHE","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},"funding":{"buy_me_a_coffee":"boshtannik"}},"created_at":"2023-08-11T16:53:49.000Z","updated_at":"2024-10-28T10:28:54.000Z","dependencies_parsed_at":"2023-08-12T00:17:22.541Z","dependency_job_id":"8c3cb1c7-d9f6-4d3d-b7f6-7b077888b8d0","html_url":"https://github.com/boshtannik/embedded-nano-mesh","commit_stats":{"total_commits":169,"total_committers":1,"mean_commits":169.0,"dds":0.0,"last_synced_commit":"2400bb614aa2cc82fa6fd8216334084dd840e3fb"},"previous_names":["boshtannik/nanomesh","boshtannik/embedded-nano-mesh"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boshtannik%2Fembedded-nano-mesh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boshtannik%2Fembedded-nano-mesh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boshtannik%2Fembedded-nano-mesh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boshtannik%2Fembedded-nano-mesh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/boshtannik","download_url":"https://codeload.github.com/boshtannik/embedded-nano-mesh/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244874390,"owners_count":20524577,"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":["embedded","iot","mesh","networking","protocol","rust-lang"],"created_at":"2024-10-28T11:04:27.476Z","updated_at":"2025-03-21T21:31:53.565Z","avatar_url":"https://github.com/boshtannik.png","language":"Rust","funding_links":["https://buymeacoffee.com/boshtannik","https://www.buymeacoffee.com/boshtannik"],"categories":[],"sub_categories":[],"readme":"# Mesh Network Protocol for embedded devices\nThis is the mesh network protocol. It allows to turn almost any\nkind of MCU device + Radio module device into a mesh node. It is designed\nto be lightweight, easy to use and portable to many plaftorms. The protocol\nmay use variety of radio modules.\n\nThe network extends and heals itself automatically by communicating\nwith other nodes, which have same protocol version installed. Most\nversions of this protocol are compatible, but for the best performance\nit is recommended to use same and the latest version.\n\nThe protocol has been tested with radio\nmodules JDY-40 during the development, and potentially can\nuse other radio modules, which might be or your choice:\n- JDY-41\n- SV-610\n- HC-11\n- HC-12\n- LC12S\n- GT-38\n- LoRa modules\n\nMCU - stands for Microcontroller Computer Unit. (Arduino, Raspberry Pi, PC, etc.)\n\n## Mesh node architecture:\n```\n (Library code runs here which turns MCU into a mesh node)\n        |                                          \n        |                                          \n        V           \n+----------------+                 +-----------------+\n|                |  (IO Interface) |                 |\n|      MCU       |\u003c---------------\u003e|   Radio module  |\n|                |                 |                 |\n+----------------+                 +-----------------+\n```\n## Network possible architecture:\n```\n+----------------+               +----------------+                 +---------------+ \n|                |               |                |                 |               | \n|      Node      |  (( Ether ))  |      Node      |   (( Ether ))   |     Node      |  \n|   Address: 1   |               |   Address: 2   |                 |   Address: 3  | \n|                |  \u003c---------\u003e  |                |  \u003c-----------\u003e  |               | \n+----------------+               +----------------+                 +---------------+ \n                  ^               ^                                                    \n                   \\             /                                                     \n                    \\           /                                                      \n       (( Ether ))   \\         /   (( Ether ))                                                    \n                      \\       /                                                        \n                       \\     /                                                         \n                        v   v                                                           \n                +----------------+                                                       \n                |                |                                                       \n                |      Node      |                                                       \n                |   Address: 4   |                                                       \n                |                |                                                       \n                +----------------+                                                       \n```\n\n## Quick links to usage examples:\n- [arduino-nano](https://github.com/boshtannik/embedded-nano-mesh-arduino-nano-example)\n- [linux](https://github.com/boshtannik/embedded-nano-mesh-linux-example)\n- [linux-cli-tool](https://github.com/boshtannik/embedded-nano-mesh-cli-tool)\n\n## Goal:\nThe goal of this project is to provide ability to build mesh\nnetwork with low memory, cheap and easily accessible microcontollers + radio modules\nor even personal computer + radio modules to participate the same network.\nThis protocol can be used for:\n- Home automation\n- Remote control\n- Remote monitoring (telemetry)\n- Decentralized messaging\n- etc.\n\n## Help to manage the development by filling that form:\nhttps://docs.google.com/forms/d/e/1FAIpQLSeB8In06PumPDxdIu-dGr79nFVyfd1nxgKnxvUXoItIFMfO7Q/viewform?usp=header\n\n## Working principle:\n### The way, how the protocol spreads the data:\nThe protocol routes the packets in the most dumb way.\nIt spereads the packet in the way, similar to the spread of the atenuating\nwave in the pool. It means, that all near devices, that can catch the packet - cathes it.\nThen the device's router - determines if the packet is reached it's\ndestination or the packet has to be transitted further into the network.\n\nRange of operation is regulated by the `lifetime` during the sending.\n\nWhile packet is being travel trough the network - it's Lifetime is decreased by intermediate devices.\nOnce `lifetime` value is reached zero during routing - the packet gets destroyed\nby the exact device which currently transits it.\n\nThe packets, that were just sent by user by `send_to_exact`, `broadcast`, `send_ping_pong` or `send_with_transaction`\nmethod in the device, which performs the operation - that packets bypasses routing and are sent directly into\nsending queue, and then into the ether. It means that lifetime of the packet is not decreased by the router\nof the device. So the message can be sent even with `lifetime` set to `0`, anyway it will be transmitted\nin the ether for the first time.\nSending of packets from the queues happends during call of `update` method.\n\nIt means, that the user can send the message with:\n* Set the `lifetime` to `0`, and the packet will be transmitted into the ether,\n  nearest device will receive it, check if the destination is reached.\n  If the destination is reached - catch the data.\n  Otherwise - try to transmit further with decrease of `lifetime` value which\n  will lead to packet destruction due to the end of packet's `lifetime`.\n\n* Also set the `lifetime` to `1`, and the packet will be transmitted into the ether,\n  nearest device will receive it, check if the destination is reached,\n  If the destination is reached - catch the data.\n  Otherwise - try to transmit further with decrease of `lifetime` value which\n  will lead to packet destruction due to the same reason.\n\n* Set the `lifetime` to `2` and the packet will be transmitted into the ether,\n  nearest device will receive it, check if the destination is reached,\n  If the destination is reached - catch the data.\n  Otherwise - try to transmit further with decrease of `lifetime` value which\n  will lead packet transition back into the ether, but with less `lifetime` value.\n\n* And so on..\n\nNode have 2 internal queues, queues are not exposed to user:\n- `send` - for packets that node holds to be sent.\n- `transit` - for packets, that node holds to be transitted from other devices.\nSizes of those queues are configurable. And their both configuration of size\nis made by `PACKET_QUEUE_SIZE` constant in `./src/mesh_lib/node/constants.rs`.\n\n### How the protocol avoid packet duplication:\nProtocol provides mechanism to prevent the network being jammed by\npacket duplication.\n\nDuring send of the packet using `send_to_exact` method - you can set `filter_out_duplication` parameter\nto `true` which prevents network from being jammed by duplicated packets.\nMethods `send_ping_pong`, `broadcast`, `send_with_transaction` has this parameter set to `true` by default.\nAs long as `send_ping_pong` and `send_with_transaction` needs more than one packet to be sent trough the network,\nand `broadcast` without `filter_out_duplication` just jams the whole network by echoed packets.\n\n`filter_out_duplication` leads protocol to spread one exact packet trough the network only once by\nsetting `ignore_duplication` flag of the packet.\n\n`filter_out_duplication` works in the next way:\n1 - Node sets `ignore_duplication` flag to the packet flags.\n2 - Once intermediate node receives the packet with `ignore_duplication` flag set to `true`,\n2.1 it remembers the `sender_device_identifier` of the packet and `id` of the packet for the\nspecified `RECEIVER_FILTER_DUPLICATE_IGNORE_PERIOD` period of time. if the packet with same\n`sender_device_identifier` and with same `id` is received again by that same node - node\nignores packet for that specified period of time.\n \n`RECEIVER_FILTER_DUPLICATE_IGNORE_PERIOD` period of time. This period is configurable in `./src/mesh_lib/node/constants.rs`.\n\n## Status:\n* The version is: 2.1.1:\n  Every planned functionality is working. It is:\n  - Send data.\n  - Receive data.\n  - Send data with ignorance of duplicated packets.\n  - Send data with limited of number of hops.\n  - Broadcast data to all nodes.\n  - Message transition by the intermediate nodes.\n  - Send data via Ping-pong method, and receive result saying that ping-pong send finished.\n  - Send data via Transaction and receive result saying that transaction being finished.\n* Fully backward compatible with version 2.0.0\n* Transaction of Backward compatibility with version 1.0.0 is restored. Only backward compatibility with version 2.1.0 is broken.\n\n## Cross-platform compatibility\nProtocol currently natively runs on:\n- Arduino nano\n- Linux (Raspberry PI, Desktop)\n\nNot tested yet on:\n- Windows\n- Mac\n- STM32\n- ESP8266\n- Raspberry PI pico\n\n## Porting to other platforms\nInitially it was designed to be able to run on Arduino nano - it can run\non huge variety of other microcontollers or personal computers.\nProtocol is using `embedded-io` trait to communicate with radio modules.\nTo run the protocol on new platform - the implementation of `embedded-io`\nmust be provided.\n\n## Issues and discussions:\nContacs are:\n- Telegram channel: [https://t.me/embedded_nano_mesh](https://t.me/embedded_nano_mesh)\n- Github: [https://github.com/boshtannik](https://github.com/boshtannik)\nThis will help this project grow.\n\n\n## Usage:\n1 - Include library.\n`Cargo.toml`:\n```\nembedded-nano-mesh = \"2.1.1\"\n```\n\n2 - Include implementation of `embedded-io` or implement it for\nyour platform.\n`Cargo.toml`:\n```\nembedded-nano-mesh-linux-io = \"0.0.1\" # For linux\n# embedded-nano-mesh-arduino-nano-io = { git = \"https://github.com/boshtannik/embedded-nano-mesh-arduino-nano-io.git\" } # For arduino\n```\n\n3 - initialize and use your implementation of `embedded-io` in your code:\n`src/main.rs`:\n```\n    let mut interface = LinuxIO::new( ... );\n    let mut mesh_node = ...;\n\n    match mesh_node.send_to_exact(\n        message.into_bytes(),               // Content.\n        ExactAddressType::new(2).unwrap(),  // Send to device with address 2.\n        10 as LifeTimeType,                 // Let message travel 10 devices before being destroyed.\n        true,                               // Filter out duplicated messages.\n    ) {\n        Ok(()) =\u003e {\n            println!(\"Message sent\")\n        }\n        Err(SendError::SendingQueueIsFull) =\u003e {\n            println!(\"SendingQueueIsFull\")\n        }\n    }\n\n    loop {\n        let _ = mesh_node.update(\u0026mut interface, current_time);\n    }\n```\nDuring sending of message you can regulate the distance that the packet will be able to\nmake - by setting the `lifetime` parameter.\nFor example:\n- setting `lifetime` to 1 will limit the message's reach to the nearest devices in the network.\n- setting `lifetime` to 10 will make the packet able to pass 10 nodes before being destroyed.\n\nFull examples are available below.\n\n## Arduino nano examples.\nUsage examples can be found here:\n- [arduino-nano](https://github.com/boshtannik/embedded-nano-mesh-arduino-nano-example)\n\nSometimes code binary might not fit onto your arduino board memory, in order to\nreduce the size of final binary - it is recommended to compile it with\n--release flag - it increases optimisation level tlat leads to smaller binary.\n\n## Linux examples.\nUsage examples can be found here:\n- [linux](https://github.com/boshtannik/embedded-nano-mesh-linux-example)\n\n## API description\nAll API of the library is provided by the `Node` structure. It offers interface for\nactions for `send_to_exact`, `broadcast`, `receive`, `send_ping_pong`, and `send_with_transaction`.\n\nThe `Node` must be constantly updated by call its `update` method.\nDuring call of `update` method - it does all internal work:\n- routes packets trough the network\n- transits packets that were sent to other devices\n- handles `lifetime` of packets\n- handles special packets like `ping` and `pong`, or any kind of transaction one.\n- saves received packets that will be available trough `receive` method.\n- sends packets, that are in the `send` queue.\n\nAs the protocol relies on physical environment - it is crucial to provide\nability to the library to rely on time counting and on communication interface.\nTime calculation is provided by `millis_provider` closure, and `interface_driver`\nis described above by `embedded-io` traits.\n\nMethods: `update`, `send_ping_pong`, `send_with_transaction` relies on `millis_provider` closure and `interface_driver`.\n`interface_driver` - is used for communication with radio modules.\n`millis_provider` - is used for time counting.\n\n### New Method\nTo initialize a `Node`, you need to provide `NodeConfig` with values:\n- `ExactAddressType`: Sets the device's identification address in the network. Multiple deivces can share same address in the same network.\n- `listen_period`: Sets period in milliseconds that determines how long the device will wait before transmitting packet to the network. It prevents network congestion.\n\n`main.rs`:\n```\nlet mut mesh_node = Node::new(NodeConfig {\n    device_address: ExactAddressType::new(1).unwrap(),\n    listen_period: 150 as ms,\n});\n```\n\n### Broadcast Method\nShares the message to all nodes in the network.\nDistance of sharing is set by `lifetime` parameter.\nIt sends packet with destination address set as\n`GeneralAddressType::BROADCAST`. Every device will treats `GeneralAddressType::Broadcast`\nas it's own address, so they keep the message as received and transits copy of that message further.\n`main.rs`:\n```\nlet _ = mesh_node.broadcast(\n    message.into_bytes(), // Content.\n    10 as LifeTimeType,   // Let message travel 10 devices before being destroyed.\n);\n```\n\n### Send to exact Method\nSends the message to device with exact address in the network.\nThe `send_to_exact` method requires the following arguments:\n\n- `data`: A `PacketDataBytes` instance to hold the message bytes.\n- `destination_device_identifier`: A `ExactAddressType` instance indicating exact target device.\n- `lifetime`: A `LifeTimeType` instance to control for how far the message can travel.\n!The term `echoed message` refers to a duplicated message that has\nbeen re-transmitted into the ether by an intermediate device.\n- `filter_out_duplication`: A boolean flag to filter out echoed messages from the network.\n\n`main.rs`:\n```\nlet _ = match mesh_node.send_to_exact(\n    message.into_bytes(),              // Content.\n    ExactAddressType::new(2).unwrap(), // Send to device with address 2.\n    10 as LifeTimeType, // Let message travel 10 devices before being destroyed.\n    true,\n);\n```\n\n### Receive Method\nOptionally returns received `Packet` instance in case\nif that packet was previously received by this exact device. It does not matter if that data\nwas sent via `broadcast`, `send_to_exact`, `ping_pong` or `send_with_transaction` method because\nanyway it was sent to that exact device.\nYou can tell which type the packet is by matching `special_state` field of returned `Packet` instance.\nField contains value of `PacketState` enum.\n\n`main.rs`:\n```\nmatch mesh_node.receive() {\n    Some(packet) =\u003e ...,\n    Node =\u003e ....,\n}\n```\n\n### Send Ping-Pong Method\nSends a message with a \"ping\" flag to the destination node and\nwaits for the same message with a \"pong\" flag. Return value tells that the end device have received\nthe message at least once or returns an error if the ping-pong exchange fails.\nThe following arguments are required:\n\n`Ping-Pong time diagram`:\n```\n            +----------+              +----------+\n            |  Sender  |              | Receiver |\n            +--------- +              +----------+\n                 |                         |     \n Ping-pong start |   --------Ping-------\u003e  |   \u003c-- Receiver has received the message\n                 |                         |\nPing-pong finish |   \u003c-------Pong--------  |\n                 |                         |\n                                    \n```\n\n- `data`: A `PacketDataBytes` instance.\n- `destination_device_identifier`: A `ExactAddressType` instance, that indicates exact target device address.\n- `lifetime`: A `LifeTimeType` instance.\n- `timeout`: An `ms` instance specifying how long to wait for a response.\n\n`main.rs`:\n```\nlet _ = mesh_node.send_ping_pong(\n    message.into_bytes(),               // Content.\n    ExactAddressType::new(2).unwrap(),  // Send to device with address 2.\n    10 as LifeTimeType,                 // Let message travel 10 devices before being destroyed.\n    1000 as ms,                         // Set timeout to 1000 ms.\n    || {\n        Instant::now()\n            .duration_since(program_start_time)\n            .as_millis() as ms\n    },                                  // Closure providing current time in milliseconds.\n    \u0026mut serial,                        // IO interface.\n);\n```\n\n### Send with Transaction Method\nSends a message and handles all further work to\nensure the target device have received it only once.\nMethod returns an error if the transaction failed.\n\n`Transaction time diagram`:\n```\n                      +----------+              +----------+\n                      |  Sender  |              | Receiver |\n                      +--------- +              +----------+\n                           |                         |     \n    *Transaction start     | ---SendTransaction---\u003e  |\n                           |                         |\n                   /       | \u003c--AcceptTransaction--  |\n(increment packet id by 1) |                         |\n                   \\       | ---InitTransaction---\u003e  |    \u003c--- Receiver has received the message\n                           |                         |\n    *Transaction finish    | \u003c--FinishTransaction--  |\n                           |                         |\n                                    \n```\n\nThe required arguments are:\n- `data`: A `PacketDataBytes` instance.\n- `destination_device_identifier`: A `ExactAddressType` instance, that indicates exact target device address.\n- `lifetime`: A `LifeTimeType` instance.\n- `timeout`: An `ms` instance to specify the response wait time.\n\n`main.rs`:\n```\nmatch mesh_node.send_with_transaction(\n    message.into_bytes(),               // Content.\n    ExactAddressType::new(2).unwrap(),  // Send to device with address 2.\n    10 as LifeTimeType,                 // Let message travel 10 devices before being destroyed.\n    2000 as ms,                         // Wait 2 seconds for response.\n    || {\n        Instant::now()\n            .duration_since(program_start_time)\n            .as_millis() as ms\n    },                                  // Closure providing current time in milliseconds.\n    \u0026mut serial,                        // IO interface.\n);\n```\n\n### Update Method\nPerforms all necessary internal operation of the `Node`.\nIt must be called in a loop with providing `embedded-io` implemented structure\nand `current_time` im milliseconds. It makes `Node` to interact with outer world.\nWith out call this method in a loop - the node will stop working.\n\n`main.rs`:\n```\nloop {\n    let current_time = Instant::now()\n        .duration_since(program_start_time)\n        .as_millis() as ms;\n\n    let _ = mesh_node.update(\u0026mut serial, current_time);\n}\n```\n\n## Reduce packet collisions\nIt is recommended to set `listen_period` value on multiple devices different from each other,\nlike:\n- device 1 - 230 ms,\n- device 2 - 240 ms,\n- device 3 - 250 ms,\nthis will reduce chance of the network to sychronize,\nand shall make less packet collisions.\nYou can play with this values in order to reduce the chance of packet collisions.\n\n### Note: The higher count of nodes in the network leads to the more network stability, but listen period must be higher in order to let devices to share same ether with less collisions. In the stable networks - there is less need to use `transaction` or `ping_pong` sending, unless, you send something very important.\n\n## No encryption\nThis protocol does not provide data encryption. To secure your data from\nbeing stolen, you should implement (de/en)cryption mechanisms independently.\n\nAll nodes must have the same version of the protocol installed to\ncommunicate. Different implementations of the `Packet` structure, or\nserialization or deserealization methods\nwill lead to communication issues.\n\n## Note\nUnder the hood, data is packed into a `Packet` instance. \nIf you need customize packets for your needs - you need configure the `Packet`\n`./src/mesh_lib/node/packet/mod.rs` and `./src/mesh_lib/node/packet/types.rs`\nAlso serialization and deserealization part shall be changed too.\n\nIt is also Pure version of protocol released. It is made to cut memory usage\neven more. It is partially compatible with embedded-nano-mesh protocol.\nPure version is located in \"pure\" branch.\n\n## Support project:\nYou can support project by\ndonate to bitcoin address: bc1qc50tm0ppj3hh7fecd6d0rv8tdygy8uhe2cemzt\nOr you can buy me a coffee:\n[![\"Buy Me A Coffee\"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/boshtannik)\n\n## License\nThis project is licensed under:\n\n- GNU General Public License, Version 3.0 ([LICENSE-GPL](LICENSE-GPL) or [GPL License](https://www.gnu.org/licenses/gpl-3.0.html))\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0))\n- MIT License ([LICENSE-MIT](LICENSE-MIT) or [MIT License](http://opensource.org/licenses/MIT))\n\nYou can choose the license that best suits your preferences.\n\n## Contribution\nYou can contribute to this project by make fork of 'main' branch and then creating\npyull request to this repository.\nPull request shall be created with next data mentioned.\n\n- Name of the issue the the pull request solves.\n- Link to the issue in the pull request description.\n- Abstract description of the cause of problem and the way it was solved.\n- Optionally notes or wishes for further maintainance or improvement.\n- Before pushing the pull request - merge it with main branch again to void all possible conflicts.\n- Push the pull request.\n\n# Current protocol configuration:\n* Amount of data that protocol can transfer is 32 bytes.\n* Amount of addresses in the network is 255. (More than 1 device can have same address)\n* Amount of packets that node can store in received queue is 5.\n* Amount of packets that node can store in transit queue is 5.\n* Amount of data about echoed packets to ignore is: 8.\n* Device keeps data about packet to ignore for 1000 ms.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboshtannik%2Fembedded-nano-mesh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fboshtannik%2Fembedded-nano-mesh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboshtannik%2Fembedded-nano-mesh/lists"}