{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreihgvxlpzfel7yxgrokceexz7j5woyn7xuvknqscr3b6awuyy4tcli",
    "uri": "at://did:plc:blwyxylzolr6frbph7eyd4n4/app.bsky.feed.post/3mfexxtgq2sp2"
  },
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreibt4kjzdl6ghvqhtibr65dnu3ul2o6554dqj4ldrsgo23rngba2gq"
    },
    "mimeType": "image/png",
    "size": 1483423
  },
  "description": "The Bitchat integration enables MeshCore devices to communicate with the Bitchat Android app through a bridge layer that translates between Bitchat protocol and MeshCore mesh networking. ",
  "path": "/bitchat-integration-for-meshcore/",
  "publishedAt": "2026-02-21T15:49:17.000Z",
  "site": "https://www.eddieoz.com",
  "tags": [
    "Button-Based Mode Switching",
    "Build Configuration",
    "Device Compatibility",
    "Protocol Specification",
    "Encapsulation Format",
    "Payloads",
    "BLE Service",
    "Architecture",
    "**πŸ“‹ See Complete Device List**",
    "Bitchat Android App",
    "companion_protocol.md",
    "packet_format.md"
  ],
  "textContent": "## Overview\n\nThe Bitchat integration enables MeshCore devices to communicate with the Bitchat Android app through a bridge layer that translates between Bitchat protocol and MeshCore mesh networking. This is an **additive feature** that preserves all existing MeshCore functionality while adding Bitchat compatibility.\n\n## Key Principles\n\n  1. **Additive, Not Substitutive** : Bitchat support is added alongside MeshCore, not replacing it\n  2. **No Infrastructure Changes** : Repeaters and room servers require no modifications\n  3. **Encapsulation Strategy** : Bitchat messages are encapsulated in standard MeshCore packets\n  4. **Backward Compatible** : Existing MeshCore nodes continue to work normally\n\n\n\n## Architecture\n\n\n    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”\n    β”‚                            MeshCore Device                               β”‚\n    β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€\n    β”‚                                                                          β”‚\n    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚\n    β”‚  β”‚    WITH DISPLAY (Menu)      β”‚    β”‚     BUTTON-ONLY (T1000-E)      β”‚  β”‚\n    β”‚  β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚    β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚  β”‚\n    β”‚  β”‚   β”‚   BITCHAT Page      β”‚   β”‚    β”‚   β”‚   5x Button Press      β”‚   β”‚  β”‚\n    β”‚  β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”   β”‚   β”‚    β”‚   β”‚   (Quintuple)          β”‚   β”‚  β”‚\n    β”‚  β”‚   β”‚  β”‚  M  β”‚  β”‚  B  β”‚   β”‚   β”‚    β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚   β”‚  β”‚\n    β”‚  β”‚   β”‚  β”‚Mesh β”‚  β”‚BitC β”‚   β”‚   β”‚    β”‚   β”‚  β”‚ LED: 3 blinks    β”‚  β”‚   β”‚  β”‚\n    β”‚  β”‚   β”‚  β””β”€β”€β”¬β”€β”€β”˜  β””β”€β”€β”¬β”€β”€β”˜   β”‚   β”‚    β”‚   β”‚  β”‚ Buzzer: tone     β”‚  β”‚   β”‚  β”‚\n    β”‚  β”‚   β”‚     β””β”€β”€β”€β”€β”¬β”€β”€β”€β”˜      β”‚   β”‚    β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚   β”‚  β”‚\n    β”‚  β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚    β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚  β”‚\n    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚\n    β”‚                 β”‚                                   β”‚                    β”‚\n    β”‚                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚\n    β”‚                                     β–Ό                                    β”‚\n    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚\n    β”‚  β”‚                    SerialBLEInterface                               β”‚ β”‚\n    β”‚  β”‚  β€’ MeshCore UART Service (6E400001-B5A3-F393-E0A9-E50E24DCCA9E)    β”‚ β”‚\n    β”‚  β”‚  β€’ Bitchat Service (F47B5E2D-4A9E-4C5A-9B3F-8E1D2C3A4B5C)        β”‚ β”‚\n    β”‚  β”‚  β€’ Only ONE service advertised at a time                           β”‚ β”‚\n    β”‚  β”‚  β€’ Auto-disconnects clients on mode switch                         β”‚ β”‚\n    β”‚  β”‚  β€’ PIN auth (MeshCore) / Open access (Bitchat)                    β”‚ β”‚\n    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚\n    β”‚                                   β”‚                                      β”‚\n    β”‚                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                        β”‚\n    β”‚                       β”‚    BitchatBridge       β”‚                        β”‚\n    β”‚                       β”‚  β€’ Encapsulate         │──► MeshCore GRP/TXT    β”‚\n    β”‚                       β”‚  β€’ Decapsulate         │◄── BC magic header     β”‚\n    β”‚                       β”‚  β€’ Loop prevention     β”‚                        β”‚\n    β”‚                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                        β”‚\n    β”‚                                   β”‚                                      β”‚\n    β”‚                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                        β”‚\n    β”‚                       β”‚       MyMesh           β”‚                        β”‚\n    β”‚                       β”‚     (MeshCore)         β”‚                        β”‚\n    β”‚                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                        β”‚\n    β”‚                                   β”‚                                      β”‚\n    β”‚                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                        β”‚\n    β”‚                       β”‚     LoRa Radio         β”‚                        β”‚\n    β”‚                       β”‚    (SX1262/etc)        β”‚                        β”‚\n    β”‚                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                        β”‚\n    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜\n\n\n### Platform Support\n\nFeature| nRF52| ESP32\n---|---|---\nMenu-based BLE mode switching| βœ…| βœ…\nButton-based BLE mode switching| βœ…| βœ…\nVisual mode indicator (M/B)| βœ…| βœ…\nLED/buzzer feedback (button-only)| βœ…| βœ…\nBitchat BLE service| βœ…| βœ…\nMeshCore UART service| βœ…| βœ…\nPIN authentication (MeshCore mode)| βœ…| βœ…\nOpen access (Bitchat mode)| βœ…| βœ…\n\n### With Display (Menu-Based)\n\nNavigate to the **BITCHAT** page and press **ENTER** to toggle between modes. Display shows large **M** (MeshCore) or **B** (Bitchat).\n\n### Button-Only (T1000-E)\n\nPress the user button **5 times rapidly** (within ~3 seconds) to toggle modes. See Button-Based Mode Switching for details.\n\n## Documentation Structure\n\nDocument| Description\n---|---\nBuild Configuration| **ENABLE_BITCHAT flag** , build options, compilation settings\nDevice Compatibility| **Complete list** of compatible/incompatible devices\nButton-Based Mode Switching| T1000-E and button-only device guide\nProtocol Specification| Bitchat wire protocol format\nEncapsulation Format| MeshCore encapsulation header and format\nPayloads| Bitchat payload types and structures\nBLE Service| BLE GATT service specification\nArchitecture| Component architecture and data flow\n\n## Quick Start\n\n### Enable Bitchat (For Developers)\n\nAdd to your `platformio.ini`:\n\n\n    build_flags =\n        -D ENABLE_BITCHAT=1\n        -D BLE_MODE_SWITCHING=1\n\n\n### Check Device Compatibility\n\nBitchat requires **either a display with buttons** OR **button-only with LED feedback** for mode switching.\n\nStatus| Device Examples| Count\n---|---|---\nβœ… **Compatible (with display)**|  Heltec V3, Wio Tracker L1, RAK4631, LilyGo T-Deck, etc.| **43 devices**\nβœ… **Compatible (button-only)**|  T1000-E| **1 device**\n❌ **Not Compatible**|  Xiao C3/nRF52, devices without screens or buttons| Future CLI support\n\n**πŸ“‹ See Complete Device List** - Find your specific device\n\n## Quick Start\n\n### Enable Bitchat Support\n\n\n    # Build with Bitchat support\n    export ENABLE_BITCHAT=1\n    pio run -e WioTrackerL1_companion_radio_ble\n\n\n### Runtime Control\n\nBitchat mode is controlled **on-device** via the UI or button presses:\n\n**With Display:**\n\n  1. Navigate to **BITCHAT** page using LEFT/RIGHT buttons\n  2. Press **ENTER** to toggle between MeshCore and Bitchat modes\n  3. Display shows large **M** (MeshCore) or **B** (Bitchat)\n\n\n\n**Button-Only (T1000-E):**\n\n  1. Press user button **5 times rapidly** (within ~3 seconds)\n  2. LED blinks 3 times (fast=Bitchat 150ms, slow=MeshCore 500ms)\n  3. Buzzer plays acknowledgment tone (if available)\n\n\n\n**Note:** The device always boots in **MeshCore mode**. Mode is not persisted across reboots.\n\n## Message Flow\n\n### Bitchat β†’ MeshCore\n\n  1. Bitchat app sends MESSAGE via BLE to `#mesh` channel\n  2. `BitchatBLEService` receives and parses message\n  3. `BitchatBridge` formats for MeshCore with `πŸ“±` prefix\n  4. Message sent as `PAYLOAD_TYPE_GRP_TXT` via mesh on `#mesh` channel\n\n\n\n### MeshCore β†’ Bitchat\n\n  1. MeshCore receives group message on `#mesh` channel\n  2. `BitchatBridge` verifies channel secret matches `SHA256(\"#mesh\")`\n  3. `BitchatBridge` detects non-Bitchat origin (no `πŸ“±` prefix)\n  4. Message formatted as Bitchat MESSAGE with TLV payload\n  5. Sent to Bitchat app via BLE notification for `#mesh` channel\n\n\n\n## #mesh Channel\n\nThe `#mesh` hashtag channel is the primary interoperability channel between Bitchat and MeshCore.\n\n### Channel Key Derivation\n\n\n    #mesh secret = first_16_bytes(SHA256(\"#mesh\"))\n                 = 0x5B664CDE0B08B220612113DB980650F3\n\n\nThe channel secret is the **first 16 bytes** of the SHA256 hash of the UTF-8 encoded channel name string (including the `#` prefix).\n\nBoth Bitchat Android app and MeshCore firmware derive the same channel secret using this mechanism, enabling seamless group messaging.\n\n### Firmware Implementation\n\n  * **Secret Computation** : `BitchatBridge::computeMeshSecret()` derives the secret at initialization\n  * **Channel Verification** : `BitchatBridge::isMeshChannel()` verifies messages belong to `#mesh`\n  * **Channel Initialization** : `MyMesh::addHashtagChannel(\"mesh\")` creates the channel on startup\n\n\n\nSee Protocol Specification for technical details.\n\n## Known Limitations\n\nIssue| Status| Workaround\n---|---|---\nBLE Notification Freeze| ⚠️ Partial| MeshCoreβ†’Bitchat notifications currently disabled on nRF52\nChannel Hash Mismatch| βœ… Fixed| #mesh channel verified by full 32-byte secret\nSimultaneous BLE Services| ❌ HW Limit| Menu-based switching (both nRF52 and ESP32)\nDM Support| 🚧 Planned| Basic infrastructure in place\nMultiple Hashtag Channels| 🚧 Planned| Currently #mesh only\n\n### Menu-Based BLE Mode Switching\n\nDue to BLE advertising size constraints, both nRF52 and ESP32 platforms use **menu-based switching** rather than simultaneous services:\n\n**Navigation:**\n\n  1. Use **LEFT/RIGHT** keys to navigate to the **BITCHAT** page\n  2. Display shows:\n     * **\"M\"** with \"MeshCore\" text β†’ MeshCore mode active\n     * **\"B\"** with \"Bitchat\" text β†’ Bitchat mode active\n  3. Press **ENTER** to toggle between modes\n\n\n\n**Platform-Specific Implementation:**\n\n  * **nRF52** : Switches advertisement data between Nordic UART and Bitchat service UUIDs\n  * **ESP32** : Uses `setBitChatMode()` to dynamically change advertised UUID via `SerialBLEInterface`\n\n\n\nBoth platforms provide identical user experience for mode switching.\n\n## Compatibility\n\nComponent| Compatibility\n---|---\nMeshCore Android App| βœ… Full (when in MeshCore BLE mode)\nBitchat Android App| βœ… Full (when in Bitchat BLE mode)\nMeshCore Repeaters| βœ… No changes required\nMeshCore Room Servers| βœ… No changes required\nOther MeshCore Nodes| βœ… Backward compatible\n\n## References\n\n  * Bitchat Android App\n  * MeshCore Companion Protocol: companion_protocol.md\n  * MeshCore Packet Structure: packet_format.md\n\n",
  "title": "Bitchat Integration for MeshCore",
  "updatedAt": "2026-02-24T19:48:13.769Z"
}