{"_id":"@chenberti/street-piano-sdk","_rev":"5-37e6f6674bd416a1b711e0bb92e38600","name":"@chenberti/street-piano-sdk","dist-tags":{"latest":"1.3.0"},"versions":{"1.0.0":{"name":"@chenberti/street-piano-sdk","version":"1.0.0","keywords":["mqtt","client","sdk","street-piano"],"author":{"name":"Hen Berti"},"license":"MIT","_id":"@chenberti/street-piano-sdk@1.0.0","maintainers":[{"name":"chenberti","email":"hennnb@gmail.com"}],"homepage":"https://github.com/henberti/street-piano-sdk#readme","bugs":{"url":"https://github.com/henberti/street-piano-sdk/issues"},"dist":{"shasum":"a2d10898c2b1f9d80f3b7a586d10ae8f2f252d39","tarball":"https://registry.npmjs.org/@chenberti/street-piano-sdk/-/street-piano-sdk-1.0.0.tgz","fileCount":7,"integrity":"sha512-QD3++v+a6gyBVBXtG9Qv6h/WXprVZI/ClaME18jJl1zf2GTlVth/FfEUD3k46nyCf+VS7C3Bb/4DMeLpsuhhbQ==","signatures":[{"sig":"MEUCIQCB7W4xNuEjaMzMy/uOYKawKtL9URNklCS3QgmqHLHjpQIgQ0yv1rA2UtmdWJzd5YFWlT8GjDYVgwEG2kLP9j3Myig=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":42124},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"import":"./dist/index.mjs","default":"./dist/index.mjs","require":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"dev":"tsup --watch","build":"tsup","clean":"rm -rf dist","prepublishOnly":"npm run build"},"_npmUser":{"name":"chenberti","email":"hennnb@gmail.com"},"repository":{"url":"git+https://github.com/henberti/street-piano-sdk.git","type":"git"},"_npmVersion":"11.6.2","description":"This SDK wraps mqtt.js and EMQX features to provide a robust, production-ready MQTT consumer for backend services.","directories":{},"sideEffects":false,"_nodeVersion":"25.0.0","dependencies":{"mqtt":"^5.14.1","uuid":"^13.0.0","dotenv":"^17.2.3"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","typescript":"^4.9.5"},"_npmOperationalInternal":{"tmp":"tmp/street-piano-sdk_1.0.0_1763577010494_0.13692496711581548","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@chenberti/street-piano-sdk","version":"1.0.1","keywords":["mqtt","client","sdk","street-piano"],"author":{"name":"Hen Berti"},"license":"MIT","_id":"@chenberti/street-piano-sdk@1.0.1","maintainers":[{"name":"chenberti","email":"hennnb@gmail.com"}],"homepage":"https://github.com/henberti/street-piano-sdk#readme","bugs":{"url":"https://github.com/henberti/street-piano-sdk/issues"},"dist":{"shasum":"57c754e797ca35fe3095c3f8c2ead1b9d50e2781","tarball":"https://registry.npmjs.org/@chenberti/street-piano-sdk/-/street-piano-sdk-1.0.1.tgz","fileCount":8,"integrity":"sha512-Chagm7uULTmFst0/7T7iPBv5AIW94NjvhF/Eq03cBaEXvSZFSjqomOM1ZRBQgy8JhK5TZY7o4BT9sHL4+7I87A==","signatures":[{"sig":"MEQCIBxB5T6wPFjrOCpo3k1Y6/7MdOSU9mmliO72oei+qV53AiA5g/Sw9vT/JckiPJyjZlRo7tCvNKg9TW5JYsKYmeIrow==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":51573},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"import":"./dist/index.mjs","default":"./dist/index.mjs","require":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"3ee06d51b5f54ad65db12940427aec5e31f34f54","scripts":{"dev":"tsup --watch","build":"tsup","clean":"rm -rf dist","prepublishOnly":"npm run build"},"_npmUser":{"name":"chenberti","email":"hennnb@gmail.com"},"repository":{"url":"git+https://github.com/henberti/street-piano-sdk.git","type":"git"},"_npmVersion":"11.6.2","description":"This SDK wraps mqtt.js and EMQX features to provide a robust, production-ready MQTT consumer for backend services.","directories":{},"sideEffects":false,"_nodeVersion":"25.0.0","dependencies":{"mqtt":"^5.14.1","uuid":"^13.0.0","dotenv":"^17.2.3"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","typescript":"^4.9.5"},"_npmOperationalInternal":{"tmp":"tmp/street-piano-sdk_1.0.1_1763578140313_0.01014529143217402","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@chenberti/street-piano-sdk","version":"1.0.2","keywords":["mqtt","client","sdk","street-piano"],"author":{"name":"Hen Berti"},"license":"MIT","_id":"@chenberti/street-piano-sdk@1.0.2","maintainers":[{"name":"chenberti","email":"hennnb@gmail.com"}],"homepage":"https://github.com/henberti/street-piano-sdk#readme","bugs":{"url":"https://github.com/henberti/street-piano-sdk/issues"},"dist":{"shasum":"cf7e10c7457c715caa687c66868be9d64dbd7439","tarball":"https://registry.npmjs.org/@chenberti/street-piano-sdk/-/street-piano-sdk-1.0.2.tgz","fileCount":8,"integrity":"sha512-IImae6/zCGRYzBC4PigMlMlO1WDdngKygk2JfYCzp8g6VL/lHK7cstSDHDuL71kZuyLNLmno7C+CD3EWPQbgxQ==","signatures":[{"sig":"MEYCIQCzUECP4tr2RaFNcaGEcunpZZLTXnnd/9w7Bf73hJzMNQIhAO87p37eaolxuaj6KoOJD22fwc7M3qXTrSgnAK4o6oZ+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":52385},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"import":"./dist/index.mjs","default":"./dist/index.mjs","require":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"035c2e0f9d14eb379fd6deadf3f4a08c73dd5742","scripts":{"dev":"tsup --watch","build":"tsup","clean":"rm -rf dist","prepublishOnly":"npm run build"},"_npmUser":{"name":"chenberti","email":"hennnb@gmail.com"},"repository":{"url":"git+https://github.com/henberti/street-piano-sdk.git","type":"git"},"_npmVersion":"11.6.2","description":"This SDK wraps mqtt.js and EMQX features to provide a robust, production-ready MQTT consumer for backend services.","directories":{},"sideEffects":false,"_nodeVersion":"25.0.0","dependencies":{"mqtt":"^5.14.1","uuid":"^13.0.0","dotenv":"^17.2.3"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","typescript":"^4.9.5"},"_npmOperationalInternal":{"tmp":"tmp/street-piano-sdk_1.0.2_1763795933954_0.30349593164715416","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@chenberti/street-piano-sdk","version":"1.0.3","keywords":["mqtt","client","sdk","street-piano"],"author":{"name":"Hen Berti"},"license":"MIT","_id":"@chenberti/street-piano-sdk@1.0.3","maintainers":[{"name":"chenberti","email":"hennnb@gmail.com"}],"homepage":"https://github.com/henberti/street-piano-sdk#readme","bugs":{"url":"https://github.com/henberti/street-piano-sdk/issues"},"dist":{"shasum":"701ddcc1c69bad4976b10d922ca6e8e6117eed80","tarball":"https://registry.npmjs.org/@chenberti/street-piano-sdk/-/street-piano-sdk-1.0.3.tgz","fileCount":8,"integrity":"sha512-zYfWPfz8SFZkcvJYkBWypoy/I/zAuNnn4x0lq0ssZap3GpZ58+t2EtxH6A5/gzC5uOVjNohOBtmZ/w68R/hxng==","signatures":[{"sig":"MEUCIQCeHd9y0tJjgaP8CfXlTd9AWEHG+qgjmCZBfGNHQpcc6wIgRHLzwPhaxdeo+Ln/DoXDuX2FEaqELNOg0zdxB8nN2OE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":52354},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"import":"./dist/index.mjs","default":"./dist/index.mjs","require":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"035c2e0f9d14eb379fd6deadf3f4a08c73dd5742","scripts":{"dev":"tsup --watch","build":"tsup","clean":"rm -rf dist","prepublishOnly":"npm run build"},"_npmUser":{"name":"chenberti","email":"hennnb@gmail.com"},"repository":{"url":"git+https://github.com/henberti/street-piano-sdk.git","type":"git"},"_npmVersion":"11.6.2","description":"This SDK wraps mqtt.js and EMQX features to provide a robust, production-ready MQTT consumer for backend services.","directories":{},"sideEffects":false,"_nodeVersion":"25.0.0","dependencies":{"mqtt":"^5.14.1","uuid":"^13.0.0","dotenv":"^17.2.3"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","typescript":"^4.9.5"},"_npmOperationalInternal":{"tmp":"tmp/street-piano-sdk_1.0.3_1763866997175_0.08577715433886368","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@chenberti/street-piano-sdk","version":"1.3.0","description":"This SDK wraps mqtt.js and EMQX features to provide a robust, production-ready MQTT consumer for backend services.","keywords":["mqtt","client","sdk","street-piano"],"repository":{"type":"git","url":"git+https://github.com/henberti/street-piano-sdk.git"},"license":"MIT","author":{"name":"Hen Berti"},"main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","sideEffects":false,"exports":{".":{"require":"./dist/index.js","import":"./dist/index.mjs","default":"./dist/index.mjs"},"./package.json":"./package.json"},"scripts":{"build":"tsup","dev":"tsup --watch","clean":"rm -rf dist","prepublishOnly":"npm run build"},"devDependencies":{"tsup":"^8.5.1","typescript":"^4.9.5"},"dependencies":{"dotenv":"^17.2.3","mqtt":"^5.14.1","uuid":"^13.0.0"},"gitHead":"cc0dd5489101f212b9120848ec57d8299df63fab","_id":"@chenberti/street-piano-sdk@1.3.0","bugs":{"url":"https://github.com/henberti/street-piano-sdk/issues"},"homepage":"https://github.com/henberti/street-piano-sdk#readme","_nodeVersion":"25.0.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-NTXLbVTuk3tJ8l6Pn8MpGwY73HC7srZxdF3tgI1f3ojNhJwpldQC7tKcIuKeurUrWbOPDK77Vpje1JG0JGjFiA==","shasum":"52550d9fe71f99540c3fa9319a03b3fd9ef53c43","tarball":"https://registry.npmjs.org/@chenberti/street-piano-sdk/-/street-piano-sdk-1.3.0.tgz","fileCount":8,"unpackedSize":132139,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDQnM8HsaUMKpqEg7DhSfeCtXBm90q5CGSaH7XAdFjTcAIgNsW6+kabVjfhTpZwi6Oc+LqUSHPsyoS/5aB5K+A/5YE="}]},"_npmUser":{"name":"chenberti","email":"hennnb@gmail.com"},"directories":{},"maintainers":[{"name":"chenberti","email":"hennnb@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/street-piano-sdk_1.3.0_1768080665617_0.38575481365846187"},"_hasShrinkwrap":false}},"time":{"created":"2025-11-19T18:30:10.414Z","modified":"2026-01-10T21:31:05.987Z","1.0.0":"2025-11-19T18:30:10.675Z","1.0.1":"2025-11-19T18:49:00.524Z","1.0.2":"2025-11-22T07:18:54.143Z","1.0.3":"2025-11-23T03:03:17.359Z","1.3.0":"2026-01-10T21:31:05.773Z"},"bugs":{"url":"https://github.com/henberti/street-piano-sdk/issues"},"author":{"name":"Hen Berti"},"license":"MIT","homepage":"https://github.com/henberti/street-piano-sdk#readme","keywords":["mqtt","client","sdk","street-piano"],"repository":{"type":"git","url":"git+https://github.com/henberti/street-piano-sdk.git"},"description":"This SDK wraps mqtt.js and EMQX features to provide a robust, production-ready MQTT consumer for backend services.","maintainers":[{"name":"chenberti","email":"hennnb@gmail.com"}],"readme":"# **Street Piano SDK**\n\nA lightweight TypeScript/Node.js SDK for connecting securely to the\\*\\* \\*\\* **Street Piano MQTT Broker** , receiving MIDI events, and reacting to piano activity in real time.\n\nThis SDK is used internally by** \\*\\***Street Piano** and by integrators who receive access credentials and a unique** \\***\\*Piano ID**from the company.\n\n---\n\n## 🚀 Installation\n\n<pre class=\"overflow-visible!\" data-start=\"446\" data-end=\"497\"><div class=\"contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary\"><div class=\"sticky top-9\"><div class=\"absolute end-0 bottom-0 flex h-9 items-center pe-2\"><div class=\"bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs\"></div></div></div><div class=\"overflow-y-auto p-4\" dir=\"ltr\"><code class=\"whitespace-pre! language-bash\"><span><span>npm install @chenberti/street-piano-sdk\n</span></span></code></div></div></pre>\n\nOr with yarn:\n\n<pre class=\"overflow-visible!\" data-start=\"514\" data-end=\"562\"><div class=\"contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary\"><div class=\"sticky top-9\"><div class=\"absolute end-0 bottom-0 flex h-9 items-center pe-2\"><div class=\"bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs\"></div></div></div><div class=\"overflow-y-auto p-4\" dir=\"ltr\"><code class=\"whitespace-pre! language-bash\"><span><span>yarn add @chenberti/street-piano-sdk\n</span></span></code></div></div></pre>\n\n---\n\n## 📦 Quick Start Example\n\n```ts\nimport { ClinetInfo, SubCB, initializeClient, parseMIDIFromMQTT } from \"@chenberti/street-piano-sdk\";\nimport dotenv from \"dotenv\";\n\ndotenv.config();\n\nconst clientInfo: ClinetInfo = {\n  password: process.env.MQTT_PASSWORD || \"\",\n  broker: process.env.MQTT_BROKER || \"\",\n  port: process.env.MQTT_PORT ? parseInt(process.env.MQTT_PORT) : 8883,\n  username: process.env.MQTT_USERNAME || \"\",\n};\n\nconst callback: SubCB = (topic, payload, packet) => {\n  try {\n    // Parse MIDI messages from the MQTT payload\n    const parsedMIDI = parseMIDIFromMQTT(payload);\n\n    // parsedMIDI can be either a single MIDIMessage or an array of MIDIMessage[]\n    if (Array.isArray(parsedMIDI)) {\n      console.log(`Received ${parsedMIDI.length} MIDI messages`);\n      parsedMIDI.forEach((msg) => {\n        console.log(`MIDI message:`, msg);\n      });\n    } else {\n      console.log(\"Received single MIDI message:\", parsedMIDI);\n    }\n  } catch (error) {\n    console.error(\"Error parsing MIDI message:\", error);\n  }\n};\n\nconst main = async () => {\n  await initializeClient(clientInfo, \"1234\", callback);\n};\n\nmain();\n```\n\n---\n\n## 🎹 Understanding the SDK\n\n### `initializeClient(clientInfo, pianoId, callback)`\n\nThis is the main function provided by the SDK.\n\n#### **Parameters**\n\n| Parameter    | Type         | Description                                                  |\n| ------------ | ------------ | ------------------------------------------------------------ |\n| `clientInfo` | `ClinetInfo` | Connection information for the MQTT broker.                  |\n| `pianoId`    | `string`     | The unique Piano ID provided by Street Piano.                |\n| `callback`   | `SubCB`      | Function that fires whenever a new MIDI message is received. |\n\n#### What\\*\\* \\*\\*`initializeClient` does\n\n- Establishes a secure MQTT connection.\n- Authenticates using your credentials.\n- Subscribes to the topic belonging to the given piano ID.\n- Listens for incoming messages.\n- Triggers your callback automatically for each new MIDI event.\n\n---\n\n## 🧩 Types\n\n### `ClinetInfo`\n\nConnection settings required to authenticate:\n\n<pre class=\"overflow-visible!\" data-start=\"2129\" data-end=\"2233\"><div class=\"contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary\"><div class=\"sticky top-9\"><div class=\"absolute end-0 bottom-0 flex h-9 items-center pe-2\"><div class=\"bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs\"></div></div></div><div class=\"overflow-y-auto p-4\" dir=\"ltr\"><code class=\"whitespace-pre! language-ts\"><span><span>interface</span><span></span><span>ClinetInfo</span><span> {\n  </span><span>username</span><span>: </span><span>string</span><span>\n  </span><span>password</span><span>: </span><span>string</span><span>\n  </span><span>broker</span><span>: </span><span>string</span><span>\n  </span><span>port</span><span>: </span><span>number</span><span>\n}\n</span></span></code></div></div></pre>\n\nThese are usually taken from environment variables.\n\n---\n\n### `SubCB`\n\nCallback definition for incoming messages:\n\n<pre class=\"overflow-visible!\" data-start=\"2350\" data-end=\"2426\"><div class=\"contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary\"><div class=\"sticky top-9\"><div class=\"absolute end-0 bottom-0 flex h-9 items-center pe-2\"><div class=\"bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs\"></div></div></div><div class=\"overflow-y-auto p-4\" dir=\"ltr\"><code class=\"whitespace-pre! language-ts\"><span><span>type</span><span></span><span>SubCB</span><span> = </span><span>(topic: string</span><span>, payload: Buffer, packet: </span><span>any</span><span>) => </span><span>void</span><span>\n</span></span></code></div></div></pre>\n\n- `topic` → MQTT topic\n- `payload` → Buffer containing the MIDI message\n- `packet` → Raw MQTT packet\n\n---\n\n## 🎵 MIDI Payload Explanation\n\nAll messages received through this SDK originate from the Street Piano system and contain **MIDI events**.\n\n### ✅ Topic format\n\nIncoming messages are published to:\n\n```\npiano/play/<piano_id>\n```\n\nExample topic:\n\n```\npiano/play/68ce6762f775e17b114e899d\n```\n\n### ✅ How to parse the message\n\nYour callback receives the MQTT `payload` as a **Buffer** containing binary MIDI data.\n\nThe SDK provides helper functions to parse MIDI messages from the payload:\n\n```ts\nimport { parseMIDIFromMQTT, parseMIDI, parseMIDIMessage, type MIDIMessage } from \"@chenberti/street-piano-sdk\";\n\nconst callback: SubCB = (topic, payload, packet) => {\n  try {\n    // Recommended: Use parseMIDIFromMQTT to automatically handle the binary format\n    const parsedMIDI = parseMIDIFromMQTT(payload);\n\n    // parsedMIDI can be either a single MIDIMessage or an array of MIDIMessage[]\n    if (Array.isArray(parsedMIDI)) {\n      console.log(`Received ${parsedMIDI.length} MIDI messages`);\n      parsedMIDI.forEach((msg) => {\n        console.log(\"MIDI message:\", msg);\n      });\n    } else {\n      console.log(\"Received single MIDI message:\", parsedMIDI);\n    }\n  } catch (error) {\n    console.error(\"Error parsing MIDI message:\", error);\n  }\n};\n```\n\n### Example parsed MIDI message\n\n```ts\n{\n  type: 'note_on',        // 'note_on' | 'note_off' | 'control_change' | 'program_change' | 'pitch_bend' | 'aftertouch' | 'unknown'\n  channel: 0,             // MIDI channel (0-15)\n  note: 91,               // MIDI note number (0-127) - present for note_on/note_off\n  velocity: 34,           // Velocity (0-127) - present for note_on/note_off\n  rawBytes: [0x90, 0x5B, 0x22]  // Raw MIDI bytes\n}\n```\n\n---\n\n### MIDI Message Fields\n\nWhen you parse a MIDI message using `parseMIDIFromMQTT()`, you get a `MIDIMessage` object with the following fields:\n\n- **`type`** - The type of MIDI message:\n\n  - `note_on`: a key was pressed\n  - `note_off`: a key was released\n  - `control_change`: control change message\n  - `program_change`: program change message\n  - `pitch_bend`: pitch bend message\n  - `aftertouch`: channel pressure/aftertouch\n  - `unknown`: unrecognized message type\n\n- **`channel`** - MIDI channel (`0–15`). Most pianos use channel `0`.\n\n- **`note`** - MIDI note number (`0–127`) - present for `note_on` and `note_off`. Each value maps to a musical pitch on the keyboard. Example: `91` is a high note.\n\n- **`velocity`** - How strongly the key was pressed (`0–127`) - present for `note_on` and `note_off`. Higher velocity = louder / stronger press. **Note:** a `note_on` with velocity `0` is automatically treated as `note_off`.\n\n- **`rawBytes`** - Array of raw MIDI bytes representing the message. Useful for debugging or further processing.\n\n### Binary Payload Format\n\nThe MQTT payload uses a binary format:\n\n- **Header**: 4 bytes (sequence number)\n- **Timestamp**: 8 bytes\n- **MIDI Data**: Length-prefixed MIDI messages `[2-byte length][MIDI bytes]` repeated\n\nThe `parseMIDIFromMQTT()` function automatically handles this format and extracts the MIDI messages for you.\n\n---\n\n## 🎵 MIDI Parsing Functions\n\nThe SDK provides several functions to parse MIDI messages:\n\n### `parseMIDIFromMQTT(mqttPayload: Buffer): ParsedMIDI`\n\n**Recommended function** for parsing MQTT payloads. Automatically detects the binary format and extracts MIDI messages.\n\n- Handles the Street Piano binary format (header + timestamp + length-prefixed MIDI data)\n- Supports JSON payloads (if needed)\n- Falls back to raw byte parsing\n- Returns a single `MIDIMessage` or an array of `MIDIMessage[]`\n\n```ts\nimport { parseMIDIFromMQTT } from \"@chenberti/street-piano-sdk\";\n\nconst parsed = parseMIDIFromMQTT(payload);\n// parsed can be MIDIMessage | MIDIMessage[]\n```\n\n### `parseMIDI(bytes: Buffer | Uint8Array | number[]): ParsedMIDI`\n\nParses raw MIDI bytes (single message or multiple messages).\n\n- Handles running status (omitted status bytes)\n- Supports multiple MIDI messages in a single byte array\n- Returns a single `MIDIMessage` or an array of `MIDIMessage[]`\n\n```ts\nimport { parseMIDI } from \"@chenberti/street-piano-sdk\";\n\nconst midiBytes = [0x90, 0x5b, 0x22]; // Note on, note 91, velocity 34\nconst parsed = parseMIDI(midiBytes);\n```\n\n### `parseMIDIMessage(bytes: Buffer | Uint8Array | number[]): MIDIMessage`\n\nParses a single MIDI message from bytes.\n\n- Requires a valid MIDI status byte (>= 0x80) at the start\n- Returns a structured `MIDIMessage` object\n\n```ts\nimport { parseMIDIMessage } from \"@chenberti/street-piano-sdk\";\n\nconst midiBytes = Buffer.from([0x90, 0x5b, 0x22]);\nconst message = parseMIDIMessage(midiBytes);\n```\n\n### MIDI Message Types\n\nThe SDK supports the following MIDI message types:\n\n- **`note_on`** - Note pressed (velocity 0 treated as `note_off`)\n- **`note_off`** - Note released\n- **`control_change`** - Control change message\n- **`program_change`** - Program change message\n- **`pitch_bend`** - Pitch bend message\n- **`aftertouch`** - Channel pressure/aftertouch\n- **`unknown`** - Unsupported or unrecognized message type\n\n### MIDIMessage Interface\n\n```ts\ninterface MIDIMessage {\n  type: \"note_on\" | \"note_off\" | \"control_change\" | \"program_change\" | \"pitch_bend\" | \"aftertouch\" | \"unknown\";\n  channel: number; // MIDI channel (0-15)\n  note?: number; // Note number (0-127) - for note_on/note_off\n  velocity?: number; // Velocity (0-127) - for note_on/note_off\n  controller?: number; // Controller number - for control_change\n  value?: number; // Controller value - for control_change\n  program?: number; // Program number - for program_change\n  pitch?: number; // Pitch bend value - for pitch_bend\n  pressure?: number; // Pressure value - for aftertouch\n  rawBytes: number[]; // Raw MIDI bytes\n}\n```\n\n---\n\n## 🎹 Piano ID (IMPORTANT)\n\nYou must pass a valid** \\*\\***Piano ID** when calling** \\*\\*`initializeClient`:\n\n<pre class=\"overflow-visible!\" data-start=\"3128\" data-end=\"3190\"><div class=\"contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary\"><div class=\"sticky top-9\"><div class=\"absolute end-0 bottom-0 flex h-9 items-center pe-2\"><div class=\"bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs\"></div></div></div><div class=\"overflow-y-auto p-4\" dir=\"ltr\"><code class=\"whitespace-pre! language-ts\"><span><span>await</span><span></span><span>initializeClient</span><span>(clientInfo, </span><span>\"1234\"</span><span>, callback)\n</span></span></code></div></div></pre>\n\nThis\\*\\* \\*\\*`\"1234\"` is a unique ID assigned by Street Piano.\n\n- Each piano has its own ID\n- You can only subscribe to pianos you were authorized to access\n- If you do not know your piano ID, contact Street Piano support\n\n---\n\n## ❗ Error Handling\n\nThe SDK automatically protects your application from:\n\n- Duplicate MQTT clientId issues\n- Reconnect storms\n- Forced disconnections\n- Session takeover events\n\nIf a fatal problem occurs, the SDK** \\*\\***stops reconnecting\\*\\* and informs you through logs/events.\n\n---\n\n## 🤝 Support\n\nFor credentials, piano IDs, or integration help:\n\n📧\\*\\* \\*\\*henb@software-berti-tech.com\n(Or your internal Street Piano engineering contact)\n\n---\n\n## ❤️ Contributions\n\nThis SDK is maintained internally.\nFeel free to open issues or PRs for improvements.\n","readmeFilename":"readme.md"}