{"id":30594107,"url":"https://github.com/zimbora/lwm2m-gw","last_synced_at":"2026-01-20T16:50:12.315Z","repository":{"id":311777379,"uuid":"1020849523","full_name":"zimbora/lwm2m-gw","owner":"zimbora","description":"lwm2m library","archived":false,"fork":false,"pushed_at":"2025-09-05T15:36:19.000Z","size":299,"stargazers_count":0,"open_issues_count":6,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-06T20:13:20.726Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zimbora.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2025-07-16T13:41:49.000Z","updated_at":"2025-09-05T15:35:37.000Z","dependencies_parsed_at":"2025-08-26T18:54:36.599Z","dependency_job_id":"c16e84e3-c4c4-4e6b-8cfe-46aa268d5b86","html_url":"https://github.com/zimbora/lwm2m-gw","commit_stats":null,"previous_names":["zimbora/lwm2m-gw"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zimbora/lwm2m-gw","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimbora%2Flwm2m-gw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimbora%2Flwm2m-gw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimbora%2Flwm2m-gw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimbora%2Flwm2m-gw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zimbora","download_url":"https://codeload.github.com/zimbora/lwm2m-gw/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimbora%2Flwm2m-gw/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279009476,"owners_count":26084609,"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","status":"online","status_checked_at":"2025-10-11T02:00:06.511Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2025-08-29T19:36:52.007Z","updated_at":"2025-10-12T00:18:39.540Z","avatar_url":"https://github.com/zimbora.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# LwM2M Node.js Library\n\n[![Tests](https://github.com/zimbora/lwm2m-node/actions/workflows/test.yml/badge.svg)](https://github.com/zimbora/lwm2m-node/actions/workflows/test.yml)\n[![codecov](https://codecov.io/gh/zimbora/lwm2m-gw/graph/badge.svg?token=3WZ5SMDRTH)](https://codecov.io/gh/zimbora/lwm2m-gw)\n[![CodeQL](https://github.com/zimbora/lwm2m-gw/actions/workflows/codeql.yml/badge.svg?branch=main)](https://github.com/zimbora/lwm2m-gw/actions/workflows/codeql.yml)\n\n[![npm version](https://img.shields.io/npm/v/lwm2m-gw.svg)](https://www.npmjs.com/package/lwm2m-gw)\n[![node](https://img.shields.io/node/v/lwm2m-gw.svg)](https://www.npmjs.com/package/lwm2m-gw)\n[![license](https://img.shields.io/npm/l/lwm2m-gw.svg)](LICENSE)\n[![npm downloads](https://img.shields.io/npm/dm/lwm2m-gw.svg)](https://www.npmjs.com/package/lwm2m-gw)\n[![types](https://img.shields.io/npm/types/lwm2m-gw.svg)](https://www.npmjs.com/package/lwm2m-gw)\n\n[![ESLint](https://img.shields.io/badge/lint-eslint-4B32C3.svg)](https://eslint.org)\n[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://prettier.io)\n[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://www.conventionalcommits.org)\n[![Release with Changesets](https://img.shields.io/badge/Release%20with-Changesets-000000.svg)](https://github.com/changesets/changesets)\n\n[![bundle size](https://img.shields.io/bundlephobia/minzip/lwm2m-gw.svg)](https://bundlephobia.com/package/lwm2m-gw)\n[![Known Vulnerabilities](https://snyk.io/test/github/zimbora/lwm2m-gw/badge.svg)](https://snyk.io/test/github/zimbora/lwm2m-gw)\n[![last commit](https://img.shields.io/github/last-commit/zimbora/lwm2m-gw.svg)](https://github.com/zimbora/lwm2m-gw/commits)\n[![issues](https://img.shields.io/github/issues/zimbora/lwm2m-gw.svg)](https://github.com/zimbora/lwm2m-gw/issues)\n[![PRs](https://img.shields.io/github/issues-pr/zimbora/lwm2m-gw.svg)](https://github.com/zimbora/lwm2m-gw/pulls)\n\n\nA comprehensive **Lightweight Machine to Machine (LwM2M)** implementation in Node.js featuring both client and server components with support for CoAP, DTLS encryption, and full bootstrap capabilities.\n\n## ⚡ Quick Demo\n\n### Complete Bootstrap Workflow\n\nExperience the full LwM2M lifecycle from device provisioning to operation:\n\n#### 1. Launch Bootstrap Server\n```bash\nnode server/examples/bootstrapServer.js | npx pino-pretty\n```\n*Handles device provisioning and security configuration on port 5684*\n\n#### 2. Launch Main LwM2M Server\n```bash\nnode server/examples/server.js | npx pino-pretty\n```\n*Manages registered devices and resource operations on port 5683*\n\n#### 3. Launch Bootstrap Client\n```bash\nnode client/examples/bootstrapClient.js | npx pino-pretty\n```\n*Simulates a device going through the complete bootstrap process*\n\n#### 4. Launch Standard Client\n```bash\nnode client/examples/client.js | npx pino-pretty\n```\n*Simulates a pre-configured device connecting directly*\n\n### 🔄 What Happens\n\nThe bootstrap client automatically:\n1. **Connects** to bootstrap server (port 5684)\n2. **Receives** security and server configuration objects\n3. **Registers** to main LwM2M server (port 5683) \n4. **Begins** normal LwM2M operations (observations, resource access)\n\n### 🔒 Secure Demo (DTLS)\n\nFor encrypted communication:\n\n```bash\n# Generate certificates\nopenssl ecparam -name secp256r1 -genkey -noout -out ecdsa.key\nopenssl req -x509 -new -key ecdsa.key -out ecdsa.crt -days 365 \\\n  -subj \"/C=US/ST=Test/L=Test/O=Test/OU=Test/CN=localhost\"\n\n# Launch secure server\nnode server/examples/dtlsServer.js\n```\n\n## 🌟 Key Features\n\n- **📱 Complete LwM2M Implementation**: Full client and server with all standard objects\n- **🔐 Security First**: DTLS encryption and comprehensive bootstrap provisioning  \n- **🚀 Production Ready**: Event-driven architecture with monitoring and analytics\n- **🔧 Developer Friendly**: Extensive examples, tests, and documentation\n- **📊 Multiple Formats**: Support for JSON, CBOR, TLV, and text data formats\n- **🔄 Real-time**: Resource observations and asynchronous notifications\n- **📡 MQTT Integration**: Bidirectional MQTT communication for device management\n\n---\n\n## ✅ LwM2M Node.js Capabilities Overview\n\n| Feature                              | 🌐 Client                         | 🖥️ Server                           | ✅ Auto Tests   |\n|--------------------------------------|-----------------------------------|-------------------------------------|-----------------|\n| **Bootstrap Server**                 |                                   |                                     |                 |\n| Bootstrap Request Handling           | ✅ Supports bootstrap requests   | ✅ Handles `/bs` endpoint           | ✅ Covered      |\n| Security Object Provisioning        | ✅ Receives provisioned config   | ✅ Creates security instances       | ✅ Covered      |\n| Server Object Provisioning          | ✅ Receives provisioned config   | ✅ Creates server instances         | ✅ Covered      |\n| Bootstrap Finish                     | ✅ Sends finish notification     | ✅ Handles `/bs-finish` endpoint    | ✅ Covered      |\n| Configuration Management             | 🕐 Planned                        | ✅ Per-endpoint configuration       | 🟡 Partial      |\n|                                      |                                   |                                     |                 |\n| **Server**                           |                                   |                                     |                 |\n| LwM2M Registration (`/rd`)           | ✅ Sends registration             | ✅ Handles registration             | ✅ Covered\t   |\n| Registration Update (`/rd/{id}`)     | ✅ Supports                       | ✅ Handles update                   | ✅ Covered      |\n| Deregistration                       | ✅ Sends                          | ✅ Handles deregistration           | ✅ Covered      |\n| Error Detection / Retry              | ✅ Logs failures                  | ✅ Detects connection loss          | 🛑 Not Covered  |\n| Event-Driven Responses               | 🕐 Planned                        | ✅ Emits payload per request        | 🟡 server       |\n|                                      |                                   |                                     |                 |\n| **Object Model / Discovery**         |                                   |                                     |                 |\n| Built-in Objects (0–6 + 3303)        | ✅ Fully implemented              | 🕐 Used via client introspection    | 🛑 Not Covered  |\n| Well-Known Core Discovery            | ✅ Responds with `\u003c/x/y/z\u003e;attr`  | ✅ Parses and lists resources       | 🟡 server       |\n| Resource Metadata (R/W/X/Obs/Units)  | ✅ Defined per object             | ✅ Discoverable via `/core`         | 🛑 Not Covered  |\n| Multiple Instances                   | 🕐 Planned                        | 🕐 Planned                          | 🛑 Not Covered  |\n|                                      |                                   |                                     |                 |\n| **Resource Access**                  |                                   |                                     |                 |\n| Resource Read                        | ✅ Responds with value            | ✅ Sends GET request                | ✅ Covered      |\n| Resource Write                       | ✅ Accepts PUT                    | ✅ Sends PUT                        | ✅ Covered      |\n| Resource Execute                     | ✅ Handles function call          | ✅ Sends POST                       | ✅ Covered      |\n| Resource Observation                 | ✅ Manages and sends notifications| ✅ Sends GET with Observe=0         | ✅ Covered      |\n| Resource Write attribute             | 🟡 Partially                      | 🛑 Not yet                          | 🛑 Not Covered  |\n| Object,InstanceId Create             | 🟡 Partially                      | 🛑 Not yet                          | 🛑 Not Covered  |\n| Object,InstaceId Delete              | 🟡 Partially                      | 🛑 Not yet                          | 🛑 Not Covered  |\n| Manual Notification Push             | ✅ Interval-based observe         | ✅ Receives notifications           | 🛑 Not Covered  |\n|                                      |                                   |                                     |                 |\n| **Data Formats**                     |                                   |                                     |                 |\n| Text Format (`Content-Format: 0`)    | ✅ Default/fallback               | ✅ Default/fallback                 | ✅ Covered      |\n| Link Format (`Content-Format: 40`)   | ✅ Encode/decode (⚠️ untested)    | ✅ Encode/decode \t\t\t         | ✅ Covered      |\n| JSON Format (`Content-Format: 50`)   | ✅ Encode/decode (⚠️ untested)    | ✅ Encode/decode \t\t\t         | ✅ Covered      |\n| TLV LwM2M (`Content-Format: 60`)     | ✅ Encode/decode (⚠️ untested)    | ✅ Encode/decode                    | ✅ Covered      |\n| JSON LwM2M (`Content-Format: 61`)    | ✅ Encode/decode (⚠️ untested)    | ✅ Encode/decode                    | ✅ Covered      |\n| CBOR LwM2M (`Content-Format: 62`)    | ✅ Encode/decode (⚠️ untested)    | ✅ Encode/decode \t\t\t         | ✅ Covered      |\n|                                      |                                   |                                     |                 |\n| **Transport Layers**                 |                                   |                                     |                 |\n| COAP                                 | ✅ Default                        | ✅ Default                          | 🛑 Not Covered  |\n| MQTT                                 | ✅ Client support                 | ✅ Server support                   | ✅ Covered      |\n| MQTT Request Handling                | 🛑 Not applicable                 | ✅ Bidirectional communication     | ✅ Covered      |\n| Bridge COAP/MQTT                     | ✅ Implemented                    | ✅ Implemented                      | 🛑 Not Covered  |\n|                                      |                                   |                                     |                 |\n| **Fota**                             |                                   |                                     |                 |\n| UDP                                  | 🕐 Planned                        | 🕐 Planned                          | 🛑 Not Covered  |\n| HTTP                                 | 🛑 Not yet                        | 🛑 Not yet                          | 🛑 Not Covered  |\n|                                      |                                   |                                     |                 |\n| **Extra Features**                   |                                   |                                     |                 |\n| Object 3303 Temperature (Simulated)  | ✅ Periodic updates               | ✅ Observes value                   | 🛑 Not Covered  |\n| Security: DTLS, OSCORE               | 🛑 OSCORE not yet                | ✅ DTLS implemented                 | 🛑 Not Covered  |\n| Persistant Storage                   | 🛑 Not yet                        | 🛑 Not yet                          | 🛑 Not Covered  |\n\n\n---\n\n## 🔒 DTLS Security (Server-Side)\n\nThis library implements **DTLS (Datagram Transport Layer Security)** for secure CoAP communication on the server side. DTLS provides encryption, authentication, and message integrity for LwM2M communications.\n\n### Features\n\n- ✅ **Certificate-based Authentication**: X.509 certificate support\n- ✅ **Encrypted Communication**: All CoAP messages encrypted via DTLS\n- ✅ **Standard Port Support**: Uses CoAPS port 5684\n- ✅ **Full LwM2M Protocol Support**: Registration, updates, observations, and resource operations over DTLS\n\n### Quick Start\n\n#### 1. Generate SSL Certificates\n\n```bash\n# Generate ECDSA private key\nopenssl ecparam -name secp256r1 -genkey -noout -out ecdsa.key\n\n# Generate self-signed certificate\nopenssl req -x509 -new -key ecdsa.key -out ecdsa.crt -days 365 \\\n  -subj \"/C=US/ST=Test/L=Test/O=Test/OU=Test/CN=localhost\"\n```\n\n#### 2. Start DTLS Server\n\n```javascript\nconst { startLwM2MDTLSCoapServer } = require('./server/resourceClient');\n\n// Validation function for client registration\nconst validation = (ep, payload) =\u003e {\n  console.log(`Validating client: ${ep}`);\n  return Promise.resolve(true);\n};\n\n// DTLS server options\nconst options = {\n  port: 5684,              // Standard CoAPS (DTLS) port\n  keyPath: './ecdsa.key',   // Path to private key\n  certPath: './ecdsa.crt',  // Path to certificate\n};\n\n// Start the secure server\nconst server = startLwM2MDTLSCoapServer(validation, options);\n```\n\n#### 3. Run Example DTLS Server\n\n```bash\nnode server/examples/dtlsServer.js\n```\n\n### Configuration Options\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `port` | number | 5684 | DTLS server port (standard CoAPS) |\n| `keyPath` | string | './server.key' | Path to RSA/ECDSA private key |\n| `certPath` | string | './server.crt' | Path to X.509 certificate |\n\n### Supported Operations\n\nAll standard LwM2M operations are supported over DTLS:\n\n- **Registration**: `/rd` endpoint with encrypted client information\n- **Registration Update**: `/rd/{location}` with secure updates\n- **Deregistration**: Secure client disconnection\n- **Resource Operations**: GET, PUT, POST operations on resources\n- **Observations**: Encrypted notification delivery\n- **Bootstrap**: Secure provisioning of client configurations\n\n### Security Considerations\n\n- **Certificate Management**: Use proper CA-signed certificates in production\n- **Key Protection**: Secure private key storage and access control\n- **Client Authentication**: Implement proper client certificate validation\n- **Regular Updates**: Keep certificates current and rotate keys periodically\n\n### Events\n\nDTLS server emits the same events as the standard CoAP server:\n\n```javascript\nconst sharedEmitter = require('./server/transport/sharedEmitter');\n\nsharedEmitter.on('registration', ({ protocol, ep, location }) =\u003e {\n  console.log(`[${protocol}] Client ${ep} registered at ${location}`);\n});\n\nsharedEmitter.on('update', ({ protocol, ep, location }) =\u003e {\n  console.log(`[${protocol}] Client ${ep} updated registration`);\n});\n\nsharedEmitter.on('deregistration', ({ protocol, ep }) =\u003e {\n  console.log(`[${protocol}] Client ${ep} deregistered`);\n});\n```\n\n---\n\n## 🚀 Bootstrap Server Details\n\nThe Bootstrap Server is a critical component that provides initial configuration and security provisioning for LwM2M devices. It follows the OMA LwM2M specification for bootstrap procedures.\n\n### Core Bootstrap Workflow\n\n```\n1. [Client] ──── POST /bs?ep=device-id ────► [Bootstrap Server]\n2. [Client] ◄─── Delete Security Objects ─── [Bootstrap Server]  \n3. [Client] ◄─── Delete Server Objects ───── [Bootstrap Server]\n4. [Client] ◄─── Write Security Instance ─── [Bootstrap Server]\n5. [Client] ◄─── Write Server Instance ───── [Bootstrap Server]\n6. [Client] ──── POST /bs-finish ──────────► [Bootstrap Server]\n7. [Client] ──── Register to LwM2M Server ─► [Main LwM2M Server]\n```\n\n### Bootstrap Objects\n\n#### Security Object (ID: 0)\nProvisioned with server connection details:\n\n```javascript\n{\n  instanceId: 0,\n  serverUri: 'coap://localhost:5683',  // Main LwM2M server URI\n  isBootstrap: false,                  // This is for main server\n  securityMode: 3,                     // 0=PSK, 1=RPK, 2=Cert, 3=NoSec\n  shortServerId: 123,                  // Server ID reference\n  publicKey: 'client-identity',        // PSK identity or certificate\n  secretKey: 'shared-secret'           // PSK key or private key\n}\n```\n\n#### Server Object (ID: 1)\nOperational parameters for the main server:\n\n```javascript\n{\n  instanceId: 0,\n  shortServerId: 123,                  // Must match Security Object\n  lifetime: 300,                       // Registration lifetime (seconds)\n  binding: 'U',                        // UDP binding\n  notificationStoring: true            // Store notifications when offline\n}\n```\n\n### Bootstrap Configuration\n\n#### Per-Device Configuration\n\n```javascript\nconst { setBootstrapConfiguration } = require('./server/handleBootstrap');\n\n// Configure specific device\nsetBootstrapConfiguration('device-001', {\n  securityInstances: [{\n    instanceId: 0,\n    serverUri: 'coaps://production-server.com:5684',\n    isBootstrap: false,\n    securityMode: 2,  // Certificate-based security\n    shortServerId: 999,\n    publicKey: 'device-001-cert.pem',\n    secretKey: 'device-001-key.pem'\n  }],\n  serverInstances: [{\n    instanceId: 0,\n    shortServerId: 999,\n    lifetime: 3600,    // 1 hour lifetime\n    binding: 'U',\n    notificationStoring: true\n  }]\n});\n```\n\n#### Bulk Configuration\n\n```javascript\n// Configure multiple devices with similar settings\nconst devices = ['device-001', 'device-002', 'device-003'];\ndevices.forEach(deviceId =\u003e {\n  setBootstrapConfiguration(deviceId, {\n    securityInstances: [{\n      instanceId: 0,\n      serverUri: 'coap://fleet-server.example.com:5683',\n      isBootstrap: false,\n      securityMode: 1,  // PSK mode\n      shortServerId: 100,\n      publicKey: deviceId,\n      secretKey: generatePSK(deviceId)  // Your PSK generation logic\n    }],\n    serverInstances: [{\n      instanceId: 0,\n      shortServerId: 100,\n      lifetime: 86400,  // 24 hours\n      binding: 'U',\n      notificationStoring: true\n    }]\n  });\n});\n```\n\n### Bootstrap Server Events\n\nMonitor bootstrap process with detailed events:\n\n```javascript\nconst sharedEmitter = require('./server/transport/sharedEmitter');\n\n// Client requested bootstrap\nsharedEmitter.on('bootstrap-request', ({ protocol, ep }) =\u003e {\n  console.log(`Bootstrap requested by ${ep} via ${protocol}`);\n  // Log for security monitoring\n  // Update device status in database\n});\n\n// Client completed bootstrap\nsharedEmitter.on('bootstrap-finish', ({ protocol, ep }) =\u003e {\n  console.log(`Bootstrap completed for ${ep}`);\n  // Mark device as ready for operations\n  // Trigger any post-bootstrap actions\n});\n```\n\n### Security Modes\n\n| Mode | Value | Description | Use Case |\n|------|--------|-------------|----------|\n| PSK | 0 | Pre-Shared Key | Simple deployments, shared secrets |\n| RPK | 1 | Raw Public Key | Certificate-less PKI |\n| Certificate | 2 | X.509 Certificates | Full PKI infrastructure |\n| NoSec | 3 | No Security | Development, testing only |\n\n### Production Deployment\n\n#### Security Best Practices\n\n```javascript\n// Production bootstrap configuration\nconst productionConfig = {\n  securityInstances: [{\n    instanceId: 0,\n    serverUri: 'coaps://lwm2m.yourcompany.com:5684',\n    isBootstrap: false,\n    securityMode: 2,  // Use certificates in production\n    shortServerId: 1,\n    publicKey: './certs/device-cert.pem',\n    secretKey: './certs/device-key.pem'\n  }],\n  serverInstances: [{\n    instanceId: 0,\n    shortServerId: 1,\n    lifetime: 3600,      // Reasonable lifetime\n    binding: 'U',\n    notificationStoring: true\n  }]\n};\n```\n\n#### Monitoring and Logging\n\n```javascript\n// Enhanced bootstrap logging\nsharedEmitter.on('bootstrap-request', ({ protocol, ep, timestamp }) =\u003e {\n  // Security logging\n  auditLog.info('Bootstrap attempt', {\n    endpoint: ep,\n    protocol: protocol,\n    timestamp: timestamp,\n    sourceIp: req.connection.remoteAddress\n  });\n  \n  // Rate limiting check\n  if (isRateLimited(ep)) {\n    throw new Error('Too many bootstrap attempts');\n  }\n});\n```\n\n---\n\n## Usage\n\n## Usage\n\n### Standard LwM2M Server\n\nStart a basic CoAP server for device registration and management:\n\n```javascript\nconst { startLwM2MCoapServer } = require('./server/resourceClient');\n\n// Validation function for client registration\nconst validation = (ep, payload) =\u003e {\n  console.log(`Registering device: ${ep}`);\n  // Add custom validation logic here\n  return Promise.resolve(true);\n};\n\n// Start server on default port 5683\nconst server = startLwM2MCoapServer(validation);\n```\n\nOr run the example server:\n\n```bash\nnode server/server.js | npx pino-pretty\n```\n\n### Bootstrap-Enabled Deployment\n\nFor production deployments with device provisioning:\n\n```bash\n# Terminal 1: Start Bootstrap Server\nnode server/bootstrapServer.js | npx pino-pretty\n\n# Terminal 2: Start Main LwM2M Server  \nnode server/server.js | npx pino-pretty\n\n# Terminal 3: Start Bootstrap Client\nnode client/bootstrapClient.js | npx pino-pretty\n```\n\n### Secure DTLS Deployment\n\nFor encrypted communication:\n\n```bash\n# Generate certificates first\nopenssl ecparam -name secp256r1 -genkey -noout -out ecdsa.key\nopenssl req -x509 -new -key ecdsa.key -out ecdsa.crt -days 365 \\\n  -subj \"/C=US/ST=Test/L=Test/O=Test/OU=Test/CN=localhost\"\n\n# Start DTLS server\nnode server/examples/dtlsServer.js\n```\n\n### Client Operations\n\n#### Resource Discovery\n\n```bash\n# Discover available resources\ncoap-cli get coap://localhost:5683/.well-known/core\n```\n\n#### Resource Operations\n\n```javascript\nconst { sendCoapRequest } = require('./server/transport/coapClient');\n\n// Read device manufacturer (Object 3, Instance 0, Resource 0)\nconst response = await sendCoapRequest('localhost', 5683, 'GET', '/3/0/0');\nconsole.log('Manufacturer:', response.payload.toString());\n\n// Write firmware update URL (Object 5, Instance 0, Resource 1)\nawait sendCoapRequest('localhost', 5683, 'PUT', '/5/0/1', {\n  payload: Buffer.from('https://example.com/firmware.bin')\n});\n\n// Execute firmware update (Object 5, Instance 0, Resource 2)\nawait sendCoapRequest('localhost', 5683, 'POST', '/5/0/2');\n```\n\n#### Observations\n\n```javascript\n// Start observing a resource\nawait sendCoapRequest('localhost', 5683, 'GET', '/3303/0/5700', {\n  observe: true,\n  confirmable: true\n});\n\n// Listen for notifications\nconst sharedEmitter = require('./server/transport/sharedEmitter');\nsharedEmitter.on('notification', ({ ep, path, payload }) =\u003e {\n  console.log(`${ep} ${path}: ${payload.toString()}`);\n});\n```\n\n### Event Monitoring\n\nMonitor all LwM2M server events:\n\n```javascript\nconst sharedEmitter = require('./server/transport/sharedEmitter');\n\n// Device lifecycle events\nsharedEmitter.on('registration', ({ protocol, ep, location }) =\u003e {\n  console.log(`[${protocol}] Device ${ep} registered at ${location}`);\n});\n\nsharedEmitter.on('update', ({ protocol, ep, location }) =\u003e {\n  console.log(`[${protocol}] Device ${ep} updated registration`);\n});\n\nsharedEmitter.on('deregistration', ({ protocol, ep }) =\u003e {\n  console.log(`[${protocol}] Device ${ep} disconnected`);\n});\n\n// Resource events\nsharedEmitter.on('notification', ({ protocol, ep, path, payload }) =\u003e {\n  console.log(`[${protocol}] ${ep} notification ${path}: ${payload.toString()}`);\n});\n\n// Bootstrap events\nsharedEmitter.on('bootstrap-request', ({ protocol, ep }) =\u003e {\n  console.log(`[${protocol}] Bootstrap requested by ${ep}`);\n});\n\nsharedEmitter.on('bootstrap-finish', ({ protocol, ep }) =\u003e {\n  console.log(`[${protocol}] Bootstrap completed for ${ep}`);\n});\n```\n\n### Resource Server (Client-Side)\n\nFor device simulation and testing:\n\n```javascript\nconst { startResourceServer } = require('./client/resourceServer');\n\n// Start client resource server with temperature sensor simulation\nconst server = startResourceServer(56831);\n\n// Server automatically provides:\n// - Device object (ID 3) with manufacturer, model, etc.\n// - Connectivity monitoring (ID 4) \n// - Temperature sensor (ID 3303) with simulated values\n```\n\n- Start the client to simulate a device with observable resources.\n- Run the server to manage registrations, handle resource operations, and observe notifications.\n- Explore `.well-known/core` for resource discovery.\n- Utilize CBOR or TLV encoding/decoding for efficient payload exchange.\n\n---\n\n## 🏗️ Server Architecture\n\nThe LwM2M server implementation provides a comprehensive device management platform with the following components:\n\n### Core Server Components\n\n#### 1. Resource Client (`server/resourceClient.js`)\n- **CoAP Server**: Standard LwM2M server on port 5683\n- **DTLS Server**: Secure LwM2M server on port 5684\n- **Protocol Support**: CoAP and DTLS transport layers\n- **Event Emission**: Real-time server events via shared emitter\n\n#### 2. Client Registry (`server/clientRegistry.js`)\n- **Device Registration**: Tracks connected devices and their metadata\n- **Location Management**: Maps registration locations to device endpoints\n- **Connection State**: Monitors device connectivity and lifecycle\n\n#### 3. Observation Registry (`server/observationRegistry.js`)\n- **Resource Observations**: Manages active resource observations\n- **Token Management**: Tracks observation tokens and associated resources\n- **Notification Routing**: Routes notifications to correct observers\n\n#### 4. Bootstrap Server (`server/bootstrap.js`)\n- **Device Provisioning**: Provides initial configuration to devices\n- **Security Management**: Provisions security objects and credentials\n- **Configuration Storage**: Per-device bootstrap configurations\n\n### Server-Side Features\n\n| Component | Feature | Description |\n|-----------|---------|-------------|\n| **Client Management** | Registration Handling | Processes device registration requests |\n| | Lifecycle Tracking | Monitors device connect/disconnect events |\n| | Metadata Storage | Stores device information and capabilities |\n| **Security** | DTLS Support | Encrypted communication with certificate validation |\n| | Bootstrap Security | Secure device provisioning and credential management |\n| | Authentication | Configurable client validation functions |\n| **Resource Operations** | Read Operations | Handle GET requests for device resources |\n| | Write Operations | Handle PUT requests to update device state |\n| | Execute Operations | Handle POST requests for device actions |\n| | Discovery | Support for `.well-known/core` resource discovery |\n| **Observations** | Resource Monitoring | Real-time monitoring of device resources |\n| | Notification Delivery | Asynchronous notification handling |\n| | Token Management | Secure observation token tracking |\n| **Data Formats** | Content Negotiation | Support for multiple data formats |\n| | Format Conversion | Automatic encoding/decoding based on Accept headers |\n| | Binary Support | Efficient binary data handling |\n\n### Event-Driven Architecture\n\nThe server uses an event-driven architecture for real-time device management:\n\n```javascript\nconst sharedEmitter = require('./server/transport/sharedEmitter');\n\n// Available server events:\n// - 'registration': Device registered\n// - 'update': Registration updated  \n// - 'deregistration': Device disconnected\n// - 'notification': Resource notification received\n// - 'bootstrap-request': Bootstrap requested\n// - 'bootstrap-finish': Bootstrap completed\n```\n\n### Configuration and Deployment\n\n#### Production Server Setup\n\n```javascript\nconst { startLwM2MCoapServer } = require('./server/resourceClient');\n\n// Custom validation for production\nconst productionValidation = async (ep, payload) =\u003e {\n  // Implement authentication logic\n  const isAuthorized = await checkDeviceAuthorization(ep);\n  if (!isAuthorized) {\n    throw new Error(`Unauthorized device: ${ep}`);\n  }\n  \n  // Validate device capabilities\n  const capabilities = parseRegistrationPayload(payload);\n  if (!isValidCapabilities(capabilities)) {\n    throw new Error(`Invalid capabilities for device: ${ep}`);\n  }\n  \n  return true;\n};\n\n// Start production server\nconst server = startLwM2MCoapServer(productionValidation, 5683);\n```\n\n#### Monitoring and Analytics\n\n```javascript\n// Real-time device monitoring\nconst deviceMetrics = new Map();\n\nsharedEmitter.on('registration', ({ ep, location }) =\u003e {\n  deviceMetrics.set(ep, {\n    registeredAt: Date.now(),\n    lastSeen: Date.now(),\n    location: location,\n    notificationCount: 0\n  });\n});\n\nsharedEmitter.on('notification', ({ ep, path, payload }) =\u003e {\n  const metrics = deviceMetrics.get(ep);\n  if (metrics) {\n    metrics.lastSeen = Date.now();\n    metrics.notificationCount++;\n    deviceMetrics.set(ep, metrics);\n  }\n});\n\n// Health check endpoint\nsetInterval(() =\u003e {\n  const activeDevices = deviceMetrics.size;\n  const totalNotifications = Array.from(deviceMetrics.values())\n    .reduce((sum, device) =\u003e sum + device.notificationCount, 0);\n  \n  console.log(`Active devices: ${activeDevices}, Total notifications: ${totalNotifications}`);\n}, 30000);\n```\n\n---\n\n## 📡 MQTT Integration\n\nThe LwM2M server provides comprehensive MQTT integration for bidirectional communication with IoT devices and external systems.\n\n### Features\n\n- **🔄 Bidirectional Communication**: Send requests to devices via MQTT and receive responses\n- **📊 Real-time Data Streaming**: Device sensor data published to MQTT topics\n- **🎯 Device Lifecycle Events**: Registration, updates, and deregistration events via MQTT\n- **🛠️ Complete LwM2M Operations**: Support for GET, PUT, POST, DELETE, DISCOVER, and OBSERVE operations\n- **🔧 Flexible Topic Structure**: Organized topic hierarchy for easy subscription management\n\n### Quick Start\n\n#### 1. Start Enhanced MQTT Gateway\n\n```javascript\nconst MqttRequestHandler = require('./server/mqttRequestHandler');\n\n// Start bidirectional MQTT gateway\nnode server/examples/serverMqttBidirectional.js\n```\n\n#### 2. Send Requests via MQTT\n\n```bash\n# Read device manufacturer\nmosquitto_pub -h localhost -t \"lwm2m/requests/device001/GET/3/0/0\" -m \"{}\"\n\n# Write temperature threshold  \nmosquitto_pub -h localhost -t \"lwm2m/requests/device001/PUT/3303/0/5601\" -m '{\"payload\": \"-10.0\"}'\n\n# Start observing temperature\nmosquitto_pub -h localhost -t \"lwm2m/requests/device001/OBSERVE/3303/0/5700\" -m \"{}\"\n```\n\n#### 3. Subscribe to Responses and Data\n\n```bash\n# Listen to device responses\nmosquitto_sub -h localhost -t \"lwm2m/responses/+/+/+\"\n\n# Listen to sensor data\nmosquitto_sub -h localhost -t \"lwm2m/+/sensor/+\"\n\n# Listen to device events\nmosquitto_sub -h localhost -t \"lwm2m/+/registered\"\n```\n\n### MQTT Topic Structure\n\n| Purpose | Topic Pattern | Example |\n|---------|---------------|---------|\n| **Inbound Requests** | `{project}/requests/{endpoint}/{method}{path}` | `lwm2m/requests/device001/GET/3/0/0` |\n| **Outbound Responses** | `{project}/responses/{endpoint}/{method}{path}` | `lwm2m/responses/device001/GET/3/0/0` |\n| **Device Data** | `{project}/{endpoint}/sensor{path}` | `lwm2m/device001/sensor/3303/0/5700` |\n| **Lifecycle Events** | `{project}/{endpoint}/{event}` | `lwm2m/device001/registered` |\n\n### Supported Operations\n\n| Method | Description | Payload Required | Example |\n|--------|-------------|------------------|---------|\n| `GET` | Read resource value | No | Read device manufacturer |\n| `PUT` | Write resource value | Yes | Update configuration |\n| `POST` | Execute resource | Optional | Trigger device reboot |\n| `DELETE` | Delete object instance | No | Remove configuration |\n| `DISCOVER` | Discover available resources | No | List all resources |\n| `OBSERVE` | Start observing resource | No | Monitor temperature |\n| `CANCEL-OBSERVE` | Stop observing resource | No | Stop monitoring |\n\n### Programming Examples\n\n#### Using the MQTT Request Handler\n\n```javascript\nconst MqttRequestHandler = require('./server/mqttRequestHandler');\n\nconst handler = new MqttRequestHandler({\n  project: 'lwm2m',\n  host: 'localhost', \n  port: 1883,\n  username: 'user',\n  password: 'pass'\n});\n\nawait handler.connect();\n```\n\n#### Integration with Existing Gateway\n\n```javascript\n// server/examples/serverMqttBidirectional.js includes:\n// - Existing outbound data publishing\n// - New inbound request handling  \n// - Unified configuration\n// - Event correlation\n```\n\n#### Demo Client\n\n```bash\n# Run interactive demo\nnode server/examples/mqttDemo.js\n```\n\nFor detailed documentation, see [MQTT Request Handler Documentation](docs/MQTT_REQUEST_HANDLER.md).\n\n---\n\n## TODO\n\n### Planned Enhancements\n\n- **OSCORE Security**: Implement Object Security for CoAP (RFC 8613)\n- **Client-Side DTLS**: Add DTLS support for LwM2M clients\n- **Persistent Storage**: Database backend for device state and configurations\n- **Error Recovery**: Enhanced error handling and automatic retry mechanisms  \n- **Performance Optimization**: Connection pooling and resource caching\n- **Advanced Analytics**: Device behavior analytics and reporting dashboards\n- **Bulk Operations**: Firmware update campaigns and mass device configuration\n- **Protocol Extensions**: SMS binding and other transport alternatives\n\n### Testing Improvements\n\n- **Integration Tests**: End-to-end bootstrap and registration workflows\n- **Performance Tests**: Load testing with multiple concurrent devices\n- **Security Tests**: Penetration testing and vulnerability assessments\n- **Compatibility Tests**: Interoperability with other LwM2M implementations\n\n---\n\n## Contributing\n\nFeel free to open issues or submit pull requests to improve this library!\n\n---\n\n*Made with ❤️ for LwM2M enthusiasts.*\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzimbora%2Flwm2m-gw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzimbora%2Flwm2m-gw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzimbora%2Flwm2m-gw/lists"}