{"id":34861160,"url":"https://github.com/armanghobadi/nomq","last_synced_at":"2026-05-24T19:36:40.455Z","repository":{"id":291470040,"uuid":"977715831","full_name":"armanghobadi/nomq","owner":"armanghobadi","description":"NoMQ is a brokerless, encrypted communication protocol for MicroPython-based IoT devices. It enables secure, peer-to-peer messaging over UDP using AES and HMAC, with support for QoS, priorities, and heartbeat signals — optimized for edge computing and smart devices.","archived":false,"fork":false,"pushed_at":"2025-11-09T00:17:05.000Z","size":1909,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-05-24T19:36:29.260Z","etag":null,"topics":["esp32","message","message-broker","micropython","network","protocol","udp-protocol"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/armanghobadi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-04T20:16:02.000Z","updated_at":"2025-11-09T00:17:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"dc3b8664-f47d-4d65-bd8e-e19349152a6d","html_url":"https://github.com/armanghobadi/nomq","commit_stats":null,"previous_names":["armanghobadi/nomq"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/armanghobadi/nomq","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/armanghobadi%2Fnomq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/armanghobadi%2Fnomq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/armanghobadi%2Fnomq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/armanghobadi%2Fnomq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/armanghobadi","download_url":"https://codeload.github.com/armanghobadi/nomq/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/armanghobadi%2Fnomq/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33448585,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-24T19:21:36.376Z","status":"ssl_error","status_checked_at":"2026-05-24T19:21:10.562Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["esp32","message","message-broker","micropython","network","protocol","udp-protocol"],"created_at":"2025-12-25T21:07:30.550Z","updated_at":"2026-05-24T19:36:40.435Z","avatar_url":"https://github.com/armanghobadi.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NoMQ: Lightweight Secure IoT Messaging Protocol 🚀\n\n![NoMQ Logo](./docs/imgs/logo.png)\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![MicroPython](https://img.shields.io/badge/Platform-MicroPython-blue.svg)](https://micropython.org/)\n[![GitHub Issues](https://img.shields.io/github/issues/armanghobadi/nomq)](https://github.com/armanghobadi/nomq/issues)\n[![GitHub Stars](https://img.shields.io/github/stars/armanghobadi/nomq)](https://github.com/armanghobadi/nomq)\n\n**NoMQ** (No Message Queue) is a lightweight, secure, and scalable messaging protocol designed for Internet of Things (IoT) applications. Built for resource-constrained devices running MicroPython (e.g., ESP32, ESP8266), NoMQ delivers enterprise-grade security, reliable message delivery, and real-time communication without the overhead of traditional message brokers. It’s ideal for industrial IoT, smart homes, and sensor networks.\n\n**NoMQ**: Secure, efficient, and brokerless messaging for IoT, designed for high reliability in industrial environments.\n\n---\n\n## 📜 Table of Contents\n\n- [Introduction](#introduction)\n- [System Objectives](#system-objectives)\n- [Protocol Structure](#protocol-structure)\n- [Features](#features)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Testing](#testing)\n- [Deployment in Real-World Scenarios](#deployment-in-real-world-scenarios)\n- [UML Diagram](#uml-diagram)\n- [License](#license)\n- [Contact](#contact)\n\n---\n\n## 🌟 Introduction\n\nNoMQ is a modern IoT messaging protocol that combines the simplicity of CoAP with the reliability of MQTT, tailored for resource-constrained environments. It uses **AES-256-CBC** encryption, **HMAC-SHA256** authentication, and a robust Quality of Service (QoS) model (0–2) to ensure secure, reliable, and efficient communication. NoMQ operates without a central broker, leveraging UDP for low-latency, peer-to-peer messaging, making it perfect for industrial automation, smart homes, and distributed sensor networks.\n\n### Why NoMQ?\n- **Lightweight**: Optimized for devices with limited memory and CPU (e.g., \u003c256 KB RAM).\n- **Secure**: End-to-end encryption and authentication protect against eavesdropping and tampering.\n- **Brokerless**: Eliminates the need for heavy message brokers, reducing latency and infrastructure costs.\n- **Reliable**: QoS levels ensure message delivery, even in unstable networks.\n- **Scalable**: Supports multiple devices, channels, and prioritized messaging.\n\n---\n\n## 🎯 System Objectives\n\nNoMQ is designed to meet the following goals:\n\n1. **Security**: Ensure data confidentiality, integrity, and authenticity using advanced cryptography.\n2. **Reliability**: Provide configurable QoS (0: fire-and-forget, 1: acknowledged, 2: assured delivery).\n3. **Efficiency**: Minimize resource usage for MicroPython devices.\n4. **Scalability**: Enable communication across multiple devices and channels.\n5. **Robustness**: Handle network failures, packet loss, and hardware constraints gracefully.\n\n---\n\n## 📡 Protocol Structure\n\nNoMQ uses a compact, secure packet structure to balance efficiency and security. Each packet consists of four layers: **Control Header**, **Security Header**, **Data Header**, and **Verification**.\n\n### Packet Structure\n| Layer            | Field                | Size (Bytes) | Description                                      |\n|------------------|----------------------|--------------|--------------------------------------------------|\n| **Control**      | Magic Number         | 2            | Fixed value (`0x4E4D`, \"NM\") for identification |\n|                  | Version              | 1            | Protocol version (`0x01`)                       |\n|                  | Packet Type          | 1            | Type (e.g., Publish: `0x01`, Subscribe: `0x02`) |\n|                  | Flags                | 1            | QoS (0–2), Retain, Priority (0–15)              |\n|                  | Packet ID            | 4            | Unique packet identifier                        |\n|                  | Session ID           | 4            | Session identifier for persistence              |\n|                  | TTL                  | 2            | Time-to-live for message expiration             |\n| **Security**     | IV                   | 16           | Initialization Vector for AES-256-CBC           |\n|                  | Timestamp            | 4            | Unix timestamp for replay protection            |\n| **Data**         | Channel ID           | 16           | SHA256 hash of channel name (truncated)         |\n|                  | Payload Length       | 2            | Length of encrypted payload                     |\n|                  | Payload              | Variable     | Encrypted data (AES-256-CBC)                    |\n| **Verification** | HMAC                 | 32           | HMAC-SHA256 for integrity and authenticity      |\n\n### Packet Types\n- `0x01`: Publish (send message to a channel)\n- `0x02`: Subscribe (join a channel)\n- `0x03`: Ack (acknowledge receipt)\n- `0x04`: Unsubscribe (leave a channel)\n- `0x05`: Heartbeat (maintain session)\n- `0x06–0x08`: QoS 2 handshake (PUBREC, PUBREL, PUBCOMP)\n\n### Flags\n- **Bits 0–1**: QoS (0: At most once, 1: At least once, 2: Exactly once)\n- **Bit 2**: Retain (store message for new subscribers)\n- **Bits 4–7**: Priority (0–15, higher = higher priority)\n\n![Wireshark Capture](./docs/imgs/wireshark.png)\n\n---\n\n## ✨ Features\n\n- **🔒 Enterprise-Grade Security**:\n  - AES-256-CBC encryption for confidentiality.\n  - HMAC-SHA256 for integrity and authentication.\n  - Replay attack protection using nonces and timestamps.\n- **📬 Reliable Messaging**:\n  - QoS levels (0–2) for flexible delivery guarantees.\n  - Automatic retries with exponential backoff.\n  - Retained messages for new subscribers.\n- **⚡ Lightweight Design**:\n  - Optimized for MicroPython on ESP32/ESP8266.\n  - Memory-efficient with configurable limits (e.g., max 50 pending messages).\n- **🌐 Scalable Communication**:\n  - Supports multiple channels (up to 20) and devices.\n  - Broadcast support (e.g., `255.255.255.255`) for network-wide messaging.\n- **🔄 Robustness**:\n  - Automatic socket reinitialization with backoff.\n  - Session renewal and nonce cleanup to prevent memory leaks.\n  - Comprehensive error handling for network and payload issues.\n\n---\n\n## 🛠️ Installation\n\n### Prerequisites\n- **Hardware**: MicroPython-compatible microcontroller (e.g., ESP32, ESP8266).\n- **Software**: MicroPython v1.20 or higher.\n- **Modules**: `uhashlib`, `ucryptolib`, `ubinascii`, `uasyncio`, `socket`, `json`, `struct`, `os`.\n- **Tools**: `esptool`, `ampy`, `rshell`, or `Thonny` for deployment.\n\n### Steps\n1. **Install MicroPython**:\n   - Download the latest firmware from [micropython.org](https://micropython.org/download/).\n   - Flash the firmware to your device:\n     ```bash\n     esptool.py --port /dev/ttyUSB0 erase_flash\n     esptool.py --port /dev/ttyUSB0 write_flash -z 0x1000 esp32-firmware.bin\n     ```\n\n2. **Clone the Repository**:\n   ```bash\n   git clone https://github.com/armanghobadi/nomq.git\n   cd nomq\n   ```\n\n3. **Deploy the Code**:\n   - Copy `nomq.py` and optionally `test_nomq.py` to your device:\n     ```bash\n     ampy --port /dev/ttyUSB0 put nomq.py\n     ampy --port /dev/ttyUSB0 put test_nomq.py\n     ```\n\n4. **Create Configuration**:\n   - Generate a `nomq_config.json` file with secure keys:\n     ```python\n     from nomq import NoMQ\n     import ubinascii, os\n     config = {\n         \"ip\": \"0.0.0.0\",\n         \"port\": 8888,\n         \"use_ipv6\": False,\n         \"encryption_key\": ubinascii.hexlify(os.urandom(32)).decode(),\n         \"hmac_key\": ubinascii.hexlify(os.urandom(32)).decode()\n     }\n     nomq = NoMQ()\n     nomq.create_config(config, \"nomq_config.json\")\n     ```\n\n---\n\n## 🚀 Usage\n\n### Example: Publish and Subscribe\nBelow is an example of using NoMQ to publish and subscribe to a channel, with WiFi setup and JSON message handling.\n\n```python\nimport uasyncio as asyncio\nimport network\nimport json\nimport time\nimport ubinascii\nfrom machine import unique_id\nfrom nomq import NoMQ\n\n# WiFi credentials\nSSID = \"your_wifi_ssid\"\nPASSWORD = \"your_wifi_password\"\n\nasync def connect_wifi():\n    wlan = network.WLAN(network.STA_IF)\n    wlan.active(True)\n    if not wlan.isconnected():\n        print(\"Connecting to WiFi...\")\n        wlan.connect(SSID, PASSWORD)\n        while not wlan.isconnected():\n            await asyncio.sleep(1)\n    print(\"WiFi connected:\", wlan.ifconfig())\n\nasync def main():\n    try:\n        await connect_wifi()\n        nomq = NoMQ(\"nomq_config.json\", log_level=\"INFO\", timeout=5)\n        \n        # Generate authentication signature\n        signature = nomq.gen_signature(\"auth\")\n        \n        # Subscribe to a channel\n        print(\"Subscribing to test/channel...\")\n        await nomq.subscribe(\"test/channel\", priority=0, signature=signature, message=\"auth\")\n        \n        # Publish a JSON message\n        message_json = {\n            \"device_id\": ubinascii.hexlify(unique_id()).decode(),\n            \"timestamp\": int(time.time()),\n            \"type\": \"environmental_sensor\",\n            \"data\": {\n                \"temperature\": {\"value\": 25.3, \"unit\": \"Celsius\"},\n                \"humidity\": {\"value\": 60.5, \"unit\": \"Percent\"},\n                \"battery\": {\"level\": 85, \"unit\": \"Percent\"}\n            },\n            \"location\": {\"latitude\": 35.6895, \"longitude\": 51.3890}\n        }\n        message = json.dumps(message_json)\n        \n        await nomq.publish(\n            \"test/channel\",\n            message,\n            qos=2,\n            retain=True,\n            ip=\"255.255.255.255\",\n            port=8888,\n            signature=signature,\n            auth_message=\"auth\"\n        )\n        \n        # Listen for messages\n        print(\"Listening for messages...\")\n        listener = await nomq.listen()\n        while True:\n            msg = listener.mssg()\n            if msg:\n                try:\n                    parsed_msg = json.loads(msg[\"message\"])\n                    print(f\"Received JSON: {msg['channel']} -\u003e {parsed_msg}\")\n                except ValueError:\n                    print(f\"Received non-JSON: {msg['channel']} -\u003e {msg['message']}\")\n            await asyncio.sleep(0.1)\n    \n    except Exception as e:\n        print(f\"Error: {e}\")\n        raise\n\ntry:\n    asyncio.run(main())\nexcept KeyboardInterrupt:\n    print(\"Terminated by user\")\nexcept Exception as e:\n    print(f\"Unexpected error: {e}\")\n```\n\n### Screenshots\n- **Sender Device**:  \n  ![Sender](./docs/imgs/sender.png)\n- **Receiver Device**:  \n  ![Receiver](./docs/imgs/receiver.png)\n- **Unit Test**:  \n  ![Test](./docs/imgs/test.png)\n\n### Key Methods\n- `subscribe(channel, priority, signature, message, addr)`: Join a channel with optional authentication.\n- `publish(channel, message, qos, retain, ttl, priority, ip, port, signature, auth_message)`: Send a message to a channel.\n- `listen()`: Asynchronously receive messages, returning a `Listener` object with a `mssg()` method.\n- `unsubscribe(channel)`: Leave a channel.\n- `create_config(config_dict, output_file)`: Generate an encrypted configuration file.\n- `gen_signature(message)`: Create an HMAC-SHA256 signature for authentication.\n- `authenticate(signature, message, addr)`: Verify device authenticity.\n\n---\n\n## 🧪 Testing\n\nNoMQ includes a comprehensive test suite (`test.py`) to validate functionality, security, and performance on MicroPython devices. The suite covers:\n\n- **Unit Tests**: Test internal functions (`gen_signature`, `_create_packet`, `_parse_packet`, etc.).\n- **Integration Tests**: Verify subscribe, publish, and listen workflows with QoS 0–2.\n- **Security Tests**: Ensure HMAC authentication and replay attack prevention.\n- **Performance Tests**: Evaluate high-load scenarios (e.g., 30 messages).\n\n### Running Tests\n1. Ensure WiFi connectivity (see `connect_wifi` above).\n2. Upload `nomq.py` and `test.py` to your device.\n3. Run the test suite:\n   ```python\n   import test\n   asyncio.run(test.main())\n   ```\n4. Check the output for test results:\n   ```\n   [INFO] PASS: HMAC-SHA256 signature generation\n   [INFO] PASS: Publish and receive message with QoS 1\n   [INFO] Test Suite: NoMQ Tests\n   [INFO] Passed: 12, Failed: 0\n   ```\n\n### Test Notes\n- Tests use a broadcast IP (`255.255.255.255`) to ensure message delivery on single-device setups.\n- The suite is optimized for MicroPython’s limited exception handling (e.g., no `UnicodeDecodeError`).\n- For low-memory devices, reduce the performance test load (e.g., 20 messages).\n\n---\n\n## 🌍 Deployment in Real-World Scenarios\n\nNoMQ is designed for various IoT applications:\n\n1. **Industrial IoT**:\n   - Securely connect sensors and controllers in factories.\n   - Example: Monitor machine health and send high-priority alerts (QoS 2).\n2. **Smart Homes**:\n   - Control devices like lights or thermostats with guaranteed delivery.\n   - Example: Toggle a relay remotely with authentication.\n3. **Sensor Networks**:\n   - Collect real-time data from distributed sensors.\n   - Example: Aggregate environmental data (temperature, humidity) across a farm.\n4. **Prototyping**:\n   - Test lightweight protocols in research or academic projects.\n   - Example: Simulate a mesh network for IoT communication.\n\n### Deployment Tips\n- **Security**: Use unique, randomly generated `encryption_key` and `hmac_key` for each deployment.\n- **Network**: Configure a stable WiFi network or dedicated access point. Use NTP for time synchronization:\n  ```python\n  import ntptime\n  ntptime.settime()\n  ```\n- **Monitoring**: Log messages to a file or external server:\n  ```python\n  with open(\"nomq_log.txt\", \"a\") as f:\n      f.write(f\"[INFO] {msg}\\n\")\n  ```\n- **Scalability**: Deploy multiple devices with unique `device_id` values and manage channel priorities.\n\n---\n\n## 📊 UML Diagram\n\nBelow is the UML class diagram for the `NoMQ` class, reflecting its structure and methods.\n\n```mermaid\nclassDiagram\n    class NoMQ {\n        -ip: str\n        -port: int\n        -use_ipv6: bool\n        -socket: socket\n        -poller: select.poll\n        -device_id: str\n        -session_id: int\n        -session_start: float\n        -channels: list\n        -retained_messages: dict\n        -pending_messages: dict\n        -nonce_set: list\n        -encryption_key: bytes\n        -hmac_key: bytes\n        -logger: SimpleLogger\n        -running: bool\n        -backoff_count: int\n        +__init__(config_file, log_level, timeout)\n        +_load_config(config_file)\n        +create_config(config_dict, output_file)\n        +_initialize_socket()\n        +_reinitialize_socket() async\n        +_get_device_id() str\n        +_generate_session_id() int\n        +_generate_packet_id() int\n        +_renew_session()\n        +_cleanup_nonces()\n        +gen_signature(message) bytes\n        +authenticate(signature, message, addr) async bool\n        +subscribe(channel, priority, signature, message, addr) async\n        +publish(channel, message, qos, retain, ttl, priority, ip, port, signature, auth_message) async\n        +listen() async Listener\n        +_create_packet(packet_type, flags, channel_id, payload, packet_id, ttl) bytes\n        +_parse_packet(data) dict\n        +send_ack(packet, addr, qos) async\n        +send_heartbeat_response(addr) async\n        +handle_qos2(packet, addr) async\n        +unsubscribe(channel) async\n        +cleanup_expired_messages() async\n        +_limit_retained_messages(channel)\n        +_limit_pending_messages()\n        +close()\n    }\n    class SimpleLogger {\n        -level: str\n        -levels: dict\n        +__init__(level)\n        +info(msg)\n        +warning(msg)\n        +error(msg)\n        +debug(msg)\n    }\n    class Listener {\n        -nomq: NoMQ\n        -message_queue: list\n        +__init__(nomq)\n        +mssg() dict\n    }\n    NoMQ --\u003e SimpleLogger : uses\n    NoMQ --\u003e Listener : returns\n```\n\n\n---\n\n## 📄 License\n\nNoMQ is licensed under the [MIT License](LICENSE). See the [LICENSE](LICENSE) file for details.\n\n---\n\n## 📬 Contact\n\nFor questions, suggestions, or support, please:\n- Open an issue on the [GitHub repository](https://github.com/armanghobadi/nomq).\n- Contact the maintainers at [arman.ghobadi.ag@gmail.com](mailto:arman.ghobadi.ag@gmail.com).\n\n---\n\n**NoMQ**: Empowering secure, lightweight, and reliable IoT communication for the future. 🌐","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farmanghobadi%2Fnomq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farmanghobadi%2Fnomq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farmanghobadi%2Fnomq/lists"}