Files
bumble_mirror/index.html
2026-01-01 02:28:22 +08:00

3392 lines
61 KiB
HTML

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="next" href="getting_started.html">
<link rel="icon" href="images/favicon.ico">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.7.1">
<title>Bumble</title>
<link rel="stylesheet" href="assets/stylesheets/main.484c7ddc.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<link rel="stylesheet" href="assets/_mkdocstrings.css">
<script>__md_scope=new URL(".",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#bumble-a-python-bluetooth-stack" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="index.html" title="Bumble" class="md-header__button md-logo" aria-label="Bumble" data-md-component="logo">
<img src="images/logo.png" alt="logo">
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
Bumble
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Introduction
</span>
</div>
</div>
</div>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<div class="md-header__source">
<a href="https://github.com/google/bumble" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"/></svg>
</div>
<div class="md-source__repository">
GitHub
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="index.html" title="Bumble" class="md-nav__button md-logo" aria-label="Bumble" data-md-component="logo">
<img src="images/logo.png" alt="logo">
</a>
Bumble
</label>
<div class="md-nav__source">
<a href="https://github.com/google/bumble" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"/></svg>
</div>
<div class="md-source__repository">
GitHub
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Introduction
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="index.html" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Introduction
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#overview" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#whats-included" class="md-nav__link">
<span class="md-ellipsis">
What's Included
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#controller" class="md-nav__link">
<span class="md-ellipsis">
Controller
</span>
</a>
<nav class="md-nav" aria-label="Controller">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#link" class="md-nav__link">
<span class="md-ellipsis">
Link
</span>
</a>
<nav class="md-nav" aria-label="Link">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#local-link" class="md-nav__link">
<span class="md-ellipsis">
Local Link
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#host" class="md-nav__link">
<span class="md-ellipsis">
Host
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#channel-manager" class="md-nav__link">
<span class="md-ellipsis">
Channel Manager
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#security-manager" class="md-nav__link">
<span class="md-ellipsis">
Security Manager
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#gatt-client" class="md-nav__link">
<span class="md-ellipsis">
GATT Client
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#gatt-server" class="md-nav__link">
<span class="md-ellipsis">
GATT Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#sdp" class="md-nav__link">
<span class="md-ellipsis">
SDP
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#rfcomm" class="md-nav__link">
<span class="md-ellipsis">
RFComm
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#device" class="md-nav__link">
<span class="md-ellipsis">
Device
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#profiles" class="md-nav__link">
<span class="md-ellipsis">
Profiles
</span>
</a>
<nav class="md-nav" aria-label="Profiles">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#a2dp" class="md-nav__link">
<span class="md-ellipsis">
A2DP
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#hfp" class="md-nav__link">
<span class="md-ellipsis">
HFP
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#hid" class="md-nav__link">
<span class="md-ellipsis">
HID
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#transports" class="md-nav__link">
<span class="md-ellipsis">
Transports
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#hardware" class="md-nav__link">
<span class="md-ellipsis">
Hardware
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#examples" class="md-nav__link">
<span class="md-ellipsis">
Examples
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#apps-tools" class="md-nav__link">
<span class="md-ellipsis">
Apps &amp; Tools
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#platforms" class="md-nav__link">
<span class="md-ellipsis">
Platforms
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#hive" class="md-nav__link">
<span class="md-ellipsis">
Hive
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#roadmap" class="md-nav__link">
<span class="md-ellipsis">
Roadmap
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="getting_started.html" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
<span class="md-ellipsis">
Development
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Development
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="development/python_environments.html" class="md-nav__link">
<span class="md-ellipsis">
Python Environments
</span>
</a>
</li>
<li class="md-nav__item">
<a href="development/contributing.html" class="md-nav__link">
<span class="md-ellipsis">
Contributing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="development/code_style.html" class="md-nav__link">
<span class="md-ellipsis">
Code Style
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" >
<div class="md-nav__link md-nav__container">
<a href="use_cases/index.html" class="md-nav__link ">
<span class="md-ellipsis">
Use Cases
</span>
</a>
<label class="md-nav__link " for="__nav_4" id="__nav_4_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Use Cases
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="use_cases/use_case_1.html" class="md-nav__link">
<span class="md-ellipsis">
Use Case 1
</span>
</a>
</li>
<li class="md-nav__item">
<a href="use_cases/use_case_2.html" class="md-nav__link">
<span class="md-ellipsis">
Use Case 2
</span>
</a>
</li>
<li class="md-nav__item">
<a href="use_cases/use_case_3.html" class="md-nav__link">
<span class="md-ellipsis">
Use Case 3
</span>
</a>
</li>
<li class="md-nav__item">
<a href="use_cases/use_case_4.html" class="md-nav__link">
<span class="md-ellipsis">
Use Case 4
</span>
</a>
</li>
<li class="md-nav__item">
<a href="use_cases/use_case_5.html" class="md-nav__link">
<span class="md-ellipsis">
Use Case 5
</span>
</a>
</li>
<li class="md-nav__item">
<a href="use_cases/use_case_6.html" class="md-nav__link">
<span class="md-ellipsis">
Use Case 6
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-ellipsis">
Components
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Components
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="components/controller.html" class="md-nav__link">
<span class="md-ellipsis">
Controller
</span>
</a>
</li>
<li class="md-nav__item">
<a href="components/host.html" class="md-nav__link">
<span class="md-ellipsis">
Host
</span>
</a>
</li>
<li class="md-nav__item">
<a href="components/gatt.html" class="md-nav__link">
<span class="md-ellipsis">
GATT
</span>
</a>
</li>
<li class="md-nav__item">
<a href="components/security_manager.html" class="md-nav__link">
<span class="md-ellipsis">
Security Manager
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6" >
<div class="md-nav__link md-nav__container">
<a href="transports/index.html" class="md-nav__link ">
<span class="md-ellipsis">
Transports
</span>
</a>
<label class="md-nav__link " for="__nav_6" id="__nav_6_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
Transports
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="transports/serial.html" class="md-nav__link">
<span class="md-ellipsis">
Serial
</span>
</a>
</li>
<li class="md-nav__item">
<a href="transports/usb.html" class="md-nav__link">
<span class="md-ellipsis">
USB
</span>
</a>
</li>
<li class="md-nav__item">
<a href="transports/pty.html" class="md-nav__link">
<span class="md-ellipsis">
PTY
</span>
</a>
</li>
<li class="md-nav__item">
<a href="transports/udp.html" class="md-nav__link">
<span class="md-ellipsis">
UDP
</span>
</a>
</li>
<li class="md-nav__item">
<a href="transports/tcp_client.html" class="md-nav__link">
<span class="md-ellipsis">
TCP Client
</span>
</a>
</li>
<li class="md-nav__item">
<a href="transports/tcp_server.html" class="md-nav__link">
<span class="md-ellipsis">
TCP Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="transports/ws_client.html" class="md-nav__link">
<span class="md-ellipsis">
WebSocket Client
</span>
</a>
</li>
<li class="md-nav__item">
<a href="transports/ws_server.html" class="md-nav__link">
<span class="md-ellipsis">
WebSocket Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="transports/vhci.html" class="md-nav__link">
<span class="md-ellipsis">
VHCI
</span>
</a>
</li>
<li class="md-nav__item">
<a href="transports/hci_socket.html" class="md-nav__link">
<span class="md-ellipsis">
HCI Socket
</span>
</a>
</li>
<li class="md-nav__item">
<a href="transports/android_emulator.html" class="md-nav__link">
<span class="md-ellipsis">
Android Emulator
</span>
</a>
</li>
<li class="md-nav__item">
<a href="transports/file.html" class="md-nav__link">
<span class="md-ellipsis">
File
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7" >
<div class="md-nav__link md-nav__container">
<a href="drivers/index.html" class="md-nav__link ">
<span class="md-ellipsis">
Drivers
</span>
</a>
<label class="md-nav__link " for="__nav_7" id="__nav_7_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
Drivers
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="drivers/realtek.html" class="md-nav__link">
<span class="md-ellipsis">
Realtek
</span>
</a>
</li>
<li class="md-nav__item">
<a href="drivers/intel.html" class="md-nav__link">
<span class="md-ellipsis">
Intel
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_8" >
<label class="md-nav__link" for="__nav_8" id="__nav_8_label" tabindex="0">
<span class="md-ellipsis">
API
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_8_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_8">
<span class="md-nav__icon md-icon"></span>
API
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="api/guide.html" class="md-nav__link">
<span class="md-ellipsis">
Guide
</span>
</a>
</li>
<li class="md-nav__item">
<a href="api/examples.html" class="md-nav__link">
<span class="md-ellipsis">
Examples
</span>
</a>
</li>
<li class="md-nav__item">
<a href="api/reference.html" class="md-nav__link">
<span class="md-ellipsis">
Reference
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_9" >
<div class="md-nav__link md-nav__container">
<a href="apps_and_tools/index.html" class="md-nav__link ">
<span class="md-ellipsis">
Apps & Tools
</span>
</a>
<label class="md-nav__link " for="__nav_9" id="__nav_9_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_9_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_9">
<span class="md-nav__icon md-icon"></span>
Apps & Tools
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="apps_and_tools/auracast.html" class="md-nav__link">
<span class="md-ellipsis">
Auracast
</span>
</a>
</li>
<li class="md-nav__item">
<a href="apps_and_tools/console.html" class="md-nav__link">
<span class="md-ellipsis">
Console
</span>
</a>
</li>
<li class="md-nav__item">
<a href="apps_and_tools/bench.html" class="md-nav__link">
<span class="md-ellipsis">
Bench
</span>
</a>
</li>
<li class="md-nav__item">
<a href="apps_and_tools/speaker.html" class="md-nav__link">
<span class="md-ellipsis">
Speaker
</span>
</a>
</li>
<li class="md-nav__item">
<a href="apps_and_tools/hci_bridge.html" class="md-nav__link">
<span class="md-ellipsis">
HCI Bridge
</span>
</a>
</li>
<li class="md-nav__item">
<a href="apps_and_tools/gg_bridge.html" class="md-nav__link">
<span class="md-ellipsis">
Golden Gate Bridge
</span>
</a>
</li>
<li class="md-nav__item">
<a href="apps_and_tools/show.html" class="md-nav__link">
<span class="md-ellipsis">
Show
</span>
</a>
</li>
<li class="md-nav__item">
<a href="apps_and_tools/gatt_dump.html" class="md-nav__link">
<span class="md-ellipsis">
GATT Dump
</span>
</a>
</li>
<li class="md-nav__item">
<a href="apps_and_tools/pair.html" class="md-nav__link">
<span class="md-ellipsis">
Pair
</span>
</a>
</li>
<li class="md-nav__item">
<a href="apps_and_tools/unbond.html" class="md-nav__link">
<span class="md-ellipsis">
Unbond
</span>
</a>
</li>
<li class="md-nav__item">
<a href="apps_and_tools/usb_probe.html" class="md-nav__link">
<span class="md-ellipsis">
USB Probe
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_10" >
<div class="md-nav__link md-nav__container">
<a href="hardware/index.html" class="md-nav__link ">
<span class="md-ellipsis">
Hardware
</span>
</a>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_10_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_10">
<span class="md-nav__icon md-icon"></span>
Hardware
</label>
<ul class="md-nav__list" data-md-scrollfix>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_11" >
<div class="md-nav__link md-nav__container">
<a href="platforms/index.html" class="md-nav__link ">
<span class="md-ellipsis">
Platforms
</span>
</a>
<label class="md-nav__link " for="__nav_11" id="__nav_11_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_11_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_11">
<span class="md-nav__icon md-icon"></span>
Platforms
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="platforms/macos.html" class="md-nav__link">
<span class="md-ellipsis">
macOS
</span>
</a>
</li>
<li class="md-nav__item">
<a href="platforms/linux.html" class="md-nav__link">
<span class="md-ellipsis">
Linux
</span>
</a>
</li>
<li class="md-nav__item">
<a href="platforms/windows.html" class="md-nav__link">
<span class="md-ellipsis">
Windows
</span>
</a>
</li>
<li class="md-nav__item">
<a href="platforms/android.html" class="md-nav__link">
<span class="md-ellipsis">
Android
</span>
</a>
</li>
<li class="md-nav__item">
<a href="platforms/zephyr.html" class="md-nav__link">
<span class="md-ellipsis">
Zephyr
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_12" >
<div class="md-nav__link md-nav__container">
<a href="examples/index.html" class="md-nav__link ">
<span class="md-ellipsis">
Examples
</span>
</a>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_12_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_12">
<span class="md-nav__icon md-icon"></span>
Examples
</label>
<ul class="md-nav__list" data-md-scrollfix>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_13" >
<div class="md-nav__link md-nav__container">
<a href="extras/index.html" class="md-nav__link ">
<span class="md-ellipsis">
Extras
</span>
</a>
<label class="md-nav__link " for="__nav_13" id="__nav_13_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<span class="md-nav__icon md-icon"></span>
Extras
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="extras/android_remote_hci.html" class="md-nav__link">
<span class="md-ellipsis">
Android Remote HCI
</span>
</a>
</li>
<li class="md-nav__item">
<a href="extras/android_bt_bench.html" class="md-nav__link">
<span class="md-ellipsis">
Android BT Bench
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_14" >
<div class="md-nav__link md-nav__container">
<a href="hive/index.html" class="md-nav__link ">
<span class="md-ellipsis">
Hive
</span>
</a>
<label class="md-nav__link " for="__nav_14" id="__nav_14_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_14">
<span class="md-nav__icon md-icon"></span>
Hive
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="hive/web/speaker/speaker.html" class="md-nav__link">
<span class="md-ellipsis">
Speaker
</span>
</a>
</li>
<li class="md-nav__item">
<a href="hive/web/scanner/scanner.html" class="md-nav__link">
<span class="md-ellipsis">
Scanner
</span>
</a>
</li>
<li class="md-nav__item">
<a href="hive/web/heart_rate_monitor/heart_rate_monitor.html" class="md-nav__link">
<span class="md-ellipsis">
Heart Rate Monitor
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#overview" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#whats-included" class="md-nav__link">
<span class="md-ellipsis">
What's Included
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#controller" class="md-nav__link">
<span class="md-ellipsis">
Controller
</span>
</a>
<nav class="md-nav" aria-label="Controller">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#link" class="md-nav__link">
<span class="md-ellipsis">
Link
</span>
</a>
<nav class="md-nav" aria-label="Link">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#local-link" class="md-nav__link">
<span class="md-ellipsis">
Local Link
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#host" class="md-nav__link">
<span class="md-ellipsis">
Host
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#channel-manager" class="md-nav__link">
<span class="md-ellipsis">
Channel Manager
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#security-manager" class="md-nav__link">
<span class="md-ellipsis">
Security Manager
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#gatt-client" class="md-nav__link">
<span class="md-ellipsis">
GATT Client
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#gatt-server" class="md-nav__link">
<span class="md-ellipsis">
GATT Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#sdp" class="md-nav__link">
<span class="md-ellipsis">
SDP
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#rfcomm" class="md-nav__link">
<span class="md-ellipsis">
RFComm
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#device" class="md-nav__link">
<span class="md-ellipsis">
Device
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#profiles" class="md-nav__link">
<span class="md-ellipsis">
Profiles
</span>
</a>
<nav class="md-nav" aria-label="Profiles">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#a2dp" class="md-nav__link">
<span class="md-ellipsis">
A2DP
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#hfp" class="md-nav__link">
<span class="md-ellipsis">
HFP
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#hid" class="md-nav__link">
<span class="md-ellipsis">
HID
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#transports" class="md-nav__link">
<span class="md-ellipsis">
Transports
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#hardware" class="md-nav__link">
<span class="md-ellipsis">
Hardware
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#examples" class="md-nav__link">
<span class="md-ellipsis">
Examples
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#apps-tools" class="md-nav__link">
<span class="md-ellipsis">
Apps &amp; Tools
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#platforms" class="md-nav__link">
<span class="md-ellipsis">
Platforms
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#hive" class="md-nav__link">
<span class="md-ellipsis">
Hive
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#roadmap" class="md-nav__link">
<span class="md-ellipsis">
Roadmap
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="bumble-a-python-bluetooth-stack">Bumble, a Python Bluetooth Stack<a class="headerlink" href="#bumble-a-python-bluetooth-stack" title="Permanent link">&para;</a></h1>
<p><img alt="logo" height="100" src="images/logo_framed.png" width="100" /></p>
<p>A Bluetooth stack, written in Python, useful for emulation, test, experimentation, and implementation of any sort of virtual device, with virtual or physical Bluetooth controllers.
The project initially only supported BLE (Bluetooth Low Energy), but support for Bluetooth Classic was
eventually added. Support for BLE is therefore currently somewhat more advanced than for Classic.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>This project is still in an early state of development where some things are still missing or broken, and what's implemented may change and evolve frequently.</p>
</div>
<h2 id="overview">Overview<a class="headerlink" href="#overview" title="Permanent link">&para;</a></h2>
<p>The goal of this project is to offer a suite of components that can be put together to implement a number of tasks related to Bluetooth. That's fairly open-ended, but at the very least, it should be possible to:</p>
<ul>
<li>Implement a virtual controller that can be attached to any compliant Bluetooth host that supports HCI.</li>
<li>Implement a Bluetooth host that communicates through a controller over HCI, including of course a virtual controller</li>
<li>Connect two or more virtual controllers together inside a single app, or across multiple apps over a network connection or local IPC</li>
<li>Scan, advertise, connect, pair</li>
<li>Implement a GATT client and server</li>
<li>Implement an SDP client and server</li>
<li>Create an L2CAP channel between two peers</li>
</ul>
<p>Some of the configurations that may be useful:</p>
<ul>
<li>A virtual controller used with an emulated or simulated device</li>
<li>A GATT client and/or GATT server test application that can be connected to a real or virtual Bluetooth device</li>
<li>Simulate certain conditions, including errors, with precise control that normal Bluetooth stacks don't offer through their standard APIs</li>
</ul>
<p>See the <a href="use_cases/index.html">use cases page</a> for more use cases.</p>
<p>The project is implemented in Python (Python &gt;= 3.10 is required). A number of APIs for functionality that is inherently I/O bound is implemented in terms of python coroutines with async IO. This means that all of the concurrent tasks run in the same thread, which makes everything much simpler and more predictable.</p>
<p><img alt="layers" src="images/bumble_layers.svg" /></p>
<h2 id="whats-included">What's Included<a class="headerlink" href="#whats-included" title="Permanent link">&para;</a></h2>
<p>Components of a Bluetooth stack:</p>
<h2 id="controller">Controller<a class="headerlink" href="#controller" title="Permanent link">&para;</a></h2>
<p>The (virtual) Controller component exposes an HCI interface to a host, and connects to a virtual link-layer bus. Several instances of this class can be connected to the same bus, in which case they can communicate with each other (both broadcast for advertising data and unicast for ACL data). The bus may be
process-local, in which case all the controllers attached to the bus run in the same process, or
it may be remote (see Remote Link), in which case several controllers in separate processes can
communicate with each other.</p>
<h3 id="link">Link<a class="headerlink" href="#link" title="Permanent link">&para;</a></h3>
<p>The Controller component communicates with other virtual controllers through a Link interface.
The link interface defines basic functionality like connection, disconnection, sending and
receiving ACL data, sending and receiving advertising data, and more.
Included in the project are two types of Link interface implementations:</p>
<h4 id="local-link">Local Link<a class="headerlink" href="#local-link" title="Permanent link">&para;</a></h4>
<p>The LocalLink implementation is a simple object used by an application that instantiates
more than one Controller objects and connects them in-memory and in-process.</p>
<h2 id="host">Host<a class="headerlink" href="#host" title="Permanent link">&para;</a></h2>
<p>The Host component connects to a controller over an HCI interface. It is responsible to sending commands and ACL data to the controller and receiving back events and ACL data.</p>
<h2 id="channel-manager">Channel Manager<a class="headerlink" href="#channel-manager" title="Permanent link">&para;</a></h2>
<p>The ChannelManager is responsible for managing L2CAP channels.</p>
<h2 id="security-manager">Security Manager<a class="headerlink" href="#security-manager" title="Permanent link">&para;</a></h2>
<p>The SecurityManager is responsible for pairing/bonding.</p>
<h2 id="gatt-client">GATT Client<a class="headerlink" href="#gatt-client" title="Permanent link">&para;</a></h2>
<p>The GATT Client offers an API to discover peer services and characteristics, reading and writing characteristics, subscribing to characteristics, and all other GATT client functions.</p>
<h2 id="gatt-server">GATT Server<a class="headerlink" href="#gatt-server" title="Permanent link">&para;</a></h2>
<p>The GATT Server offers an API to expose services and characteristics, responding to reads and writes on characteristics, handling subscriptions to characteristics, and all other GATT server functions.</p>
<h2 id="sdp">SDP<a class="headerlink" href="#sdp" title="Permanent link">&para;</a></h2>
<p>SDP implements the service discovery protocol for Bluetooth Classic.</p>
<h2 id="rfcomm">RFComm<a class="headerlink" href="#rfcomm" title="Permanent link">&para;</a></h2>
<p>RFComm is a bi-directional serial-port-like protocol. It is used in several profiles.</p>
<h2 id="device">Device<a class="headerlink" href="#device" title="Permanent link">&para;</a></h2>
<p>The Device component it a compound object that ties together a Host, GATT Client, GATT Server, L2CAP channel access, advertising and scanning, and more.</p>
<h2 id="profiles">Profiles<a class="headerlink" href="#profiles" title="Permanent link">&para;</a></h2>
<p>Profiles are ways of using the underlying protocols for certain well-defined used cases, like playing music, implementing a headset, and so on.</p>
<h3 id="a2dp">A2DP<a class="headerlink" href="#a2dp" title="Permanent link">&para;</a></h3>
<p>A2DP is the Advanced Audio Profile, which enables asynchronous streaming of audio to speakers, or from microphones. Both the "source" (typically music playback source) and "sink" (typically a speaker) functions of A2DP.</p>
<h3 id="hfp">HFP<a class="headerlink" href="#hfp" title="Permanent link">&para;</a></h3>
<p>Hands Free Profile. Used for headsets.</p>
<h3 id="hid">HID<a class="headerlink" href="#hid" title="Permanent link">&para;</a></h3>
<p>Human Interface Device. For keyboards, mice, etc.</p>
<h2 id="transports">Transports<a class="headerlink" href="#transports" title="Permanent link">&para;</a></h2>
<p>The Hosts and Controllers communicate over a transport, which is responsible for sending/receiving
HCI packets.
Several types of transports are supported:</p>
<ul>
<li><strong>In Process</strong>: HCI packets are passed via a function call</li>
<li>Serial: interface with a controller over a serial port (HCI UART, like a development board or serial Bluetooth dongle)</li>
<li><strong>USB</strong>: interface with a controller over USB (HCI USB, like a Bluetooth USB dongle)</li>
<li><strong>UDP</strong>: packets are sent to a specified host/port and received on a specified port over a UDP socket</li>
<li><strong>TCP Client</strong>: a connection to a TCP server is made, after which HCI packets are sent/received over a TCP socket</li>
<li><strong>TCP Server</strong>: listens for a TCP client on a specified port. When a client connection is made, HCI packets are sent/received over a TCP socket</li>
<li><strong>WebSocket Client</strong>: a connection to a WebSocket server is made, after which HCI packets are sent/received over the socket.</li>
<li><strong>WebSocket Server</strong>: listens for a WebSocket client on a specified port. When a client connection is made, HCI packets are sent/received over the socket.</li>
<li><strong>PTY</strong>: a PTY (pseudo terminal) is used to send/receive HCI packets. This is convenient to expose a virtual controller as if it were an HCI UART</li>
<li><strong>VHCI</strong>: used to attach a virtual controller to a Bluetooth stack on platforms that support it.</li>
<li><strong>HCI</strong> Socket: an HCI socket, on platforms that support it, to send/receive HCI packets to/from an HCI controller managed by the OS.</li>
<li><strong>Android Emulator</strong>: a gRPC connection to an Android emulator is used to setup either an HCI interface to the emulator's "Root Canal" virtual controller, or attach a virtual controller to the Android Bluetooth host stack.</li>
<li><strong>File</strong>: HCI packets are read/written to a file-like node in the filesystem.</li>
</ul>
<p>A Bumble Host object communicates with a Bumble Controller object, or external Controller, via a Transport connection. A Bumble Controller object communicates with a Bumble Host, or external Host, via a Transport connection. When both the Host and Controller are Bumble objects, they typically communicate In Process, or via a Link Relay.</p>
<p>See the <a href="transports/index.html">Transports page</a> for details.</p>
<h2 id="hardware">Hardware<a class="headerlink" href="#hardware" title="Permanent link">&para;</a></h2>
<p>The Host part of the stack can interact with Bumble's Controller implementation, but also with external hardware controllers.</p>
<p>See the <a href="hardware/index.html">Hardware page</a> for details.</p>
<h2 id="examples">Examples<a class="headerlink" href="#examples" title="Permanent link">&para;</a></h2>
<p>See the <a href="examples/index.html">Examples page</a></p>
<h2 id="apps-tools">Apps &amp; Tools<a class="headerlink" href="#apps-tools" title="Permanent link">&para;</a></h2>
<p>See the <a href="apps_and_tools/index.html">Apps &amp; Tools page</a></p>
<h2 id="platforms">Platforms<a class="headerlink" href="#platforms" title="Permanent link">&para;</a></h2>
<p>The core library should work on any platform on which you can run Python3.
Some platforms support features that not all platforms support</p>
<ul>
<li><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11"/></svg></span> macOS - see the <a href="platforms/macos.html">macOS platform page</a></li>
<li><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14.62 8.35c-.42.28-1.75 1.04-1.95 1.19-.39.31-.75.29-1.14-.01-.2-.16-1.53-.92-1.95-1.19-.48-.31-.45-.7.08-.92 1.64-.69 3.28-.64 4.91.03.49.21.51.6.05.9m7.22 7.28c-.93-2.09-2.2-3.99-3.84-5.66a4.3 4.3 0 0 1-1.06-1.88c-.1-.33-.17-.67-.24-1.01-.2-.88-.29-1.78-.7-2.61-.73-1.58-2-2.4-3.84-2.47-1.81.05-3.16.81-3.95 2.4-.21.43-.36.88-.46 1.34-.17.76-.32 1.55-.5 2.32-.15.65-.45 1.21-.96 1.71-1.61 1.57-2.9 3.37-3.88 5.35-.14.29-.28.58-.37.88-.19.66.29 1.12.99.96.44-.09.88-.18 1.3-.31.41-.15.57-.05.67.35.65 2.15 2.07 3.66 4.24 4.5 4.12 1.56 8.93-.66 9.97-4.58.07-.27.17-.37.47-.27.46.14.93.24 1.4.35.49.09.85-.16.92-.64.03-.26-.06-.49-.16-.73"/></svg></span> Linux - see the <a href="platforms/linux.html">Linux platform page</a></li>
<li><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 12V6.75l6-1.32v6.48zm17-9v8.75l-10 .15V5.21zM3 13l6 .09v6.81l-6-1.15zm17 .25V22l-10-1.91V13.1z"/></svg></span> Windows - see the <a href="platforms/windows.html">Windows platform page</a></li>
<li><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M16.61 15.15c-.46 0-.84-.37-.84-.83s.38-.82.84-.82.84.36.84.82-.38.83-.84.83m-9.2 0c-.46 0-.84-.37-.84-.83s.38-.82.84-.82.83.36.83.82-.37.83-.83.83m9.5-5.01 1.67-2.88c.09-.17.03-.38-.13-.47-.17-.1-.38-.04-.45.13l-1.71 2.91A10.15 10.15 0 0 0 12 8.91c-1.53 0-3 .33-4.27.91L6.04 6.91a.334.334 0 0 0-.47-.13c-.17.09-.22.3-.13.47l1.66 2.88C4.25 11.69 2.29 14.58 2 18h20c-.28-3.41-2.23-6.3-5.09-7.86"/></svg></span> Android - see the <a href="platforms/android.html">Android platform page</a></li>
</ul>
<p>See the <a href="platforms/index.html">Platforms page</a> for details.</p>
<h2 id="hive">Hive<a class="headerlink" href="#hive" title="Permanent link">&para;</a></h2>
<p>The Hive is a collection of example apps and virtual devices that are implemented using the
Python Bumble API, running entirely in a web page. This is a convenient way to try out some
of the examples without any Python installation, when you have some other virtual Bluetooth
device that you can connect to or from, such as the Android Emulator.</p>
<p>See the <a href="hive/index.html">Bumble Hive</a> for details.</p>
<h2 id="roadmap">Roadmap<a class="headerlink" href="#roadmap" title="Permanent link">&para;</a></h2>
<p>Future features to be considered include:</p>
<ul>
<li>More profiles</li>
<li>More device examples</li>
<li>Add a new type of virtual link (beyond the two existing ones) to allow for link-level simulation (timing, loss, etc)</li>
<li>Bindings for languages other than Python</li>
<li>RPC interface to expose most of the API for remote use</li>
<li>(...suggest anything you want...)</li>
</ul>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="getting_started.html" title="Getting Started" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
Getting Started
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
<div class="md-footer-copyright__highlight">
Copyright 2021-2023 Google LLC
</div>
</div>
<div class="md-social">
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"annotate": null, "base": ".", "features": ["navigation.indexes"], "search": "assets/javascripts/workers/search.2c215733.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
<script src="assets/javascripts/bundle.79ae519e.min.js"></script>
</body>
</html>