1import {LitElement, html} from 'https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js'; 2 3class BumbleControls extends LitElement { 4 constructor() { 5 super(); 6 this.bumbleLoaded = false; 7 this.connected = false; 8 } 9 10 render() { 11 return html` 12 <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"> 13 <dialog id="settings-dialog" @close=${this.onSettingsDialogClose} style="font-family:sans-serif"> 14 <p>WebSocket URL for HCI transport</p> 15 <form> 16 <input id="settings-hci-url-input" type="text" size="50"></input> 17 <button value="cancel" formmethod="dialog">Cancel</button> 18 <button @click=${this.saveSettings}>Save</button> 19 </form> 20 </dialog> 21 <button @click=${this.openSettingsDialog} class="mdc-icon-button material-icons"><div class="mdc-icon-button__ripple"></div>settings</button> 22 <button @click=${this.connectBluetooth} ?disabled=${!this.canConnect()} class="mdc-icon-button material-icons"><div class="mdc-icon-button__ripple"></div>bluetooth</button> 23 <button @click=${this.stop} ?disabled=${!this.connected} class="mdc-icon-button material-icons"><div class="mdc-icon-button__ripple"></div>stop</button> 24 ` 25 } 26 27 get settingsHciUrlInput() { 28 return this.renderRoot.querySelector('#settings-hci-url-input'); 29 } 30 31 get settingsDialog() { 32 return this.renderRoot.querySelector('#settings-dialog'); 33 } 34 35 canConnect() { 36 return this.bumbleLoaded && !this.connected && this.getHciUrl(); 37 } 38 39 getHciUrl() { 40 // Look for a URL parameter setting first. 41 const params = (new URL(document.location)).searchParams; 42 let hciWsUrl = params.get("hci"); 43 if (hciWsUrl) { 44 return hciWsUrl; 45 } 46 47 // Try to load the setting from storage. 48 hciWsUrl = localStorage.getItem("hciWsUrl"); 49 if (hciWsUrl) { 50 return hciWsUrl; 51 } 52 53 // Finally, default to nothing. 54 return null; 55 } 56 57 openSettingsDialog() { 58 const hciUrl = this.getHciUrl(); 59 if (hciUrl) { 60 this.settingsHciUrlInput.value = hciUrl; 61 } else { 62 // Start with default, assuming port 7681. 63 this.settingsHciUrlInput.value = "ws://localhost:7681/v1/websocket/bt" 64 } 65 this.settingsDialog.showModal(); 66 } 67 68 onSettingsDialogClose() { 69 if (this.settingsDialog.returnValue === "cancel") { 70 return; 71 } 72 if (this.settingsHciUrlInput.value) { 73 localStorage.setItem("hciWsUrl", this.settingsHciUrlInput.value); 74 } else { 75 localStorage.removeItem("hciWsUrl"); 76 } 77 78 this.requestUpdate(); 79 } 80 81 saveSettings(event) { 82 event.preventDefault(); 83 this.settingsDialog.close(this.settingsHciUrlInput.value); 84 } 85 86 async connectBluetooth() { 87 this.connected = await this.connector(this.getHciUrl()); 88 this.requestUpdate(); 89 } 90 91 async stop() { 92 await this.stopper(); 93 this.connected = false; 94 this.requestUpdate(); 95 } 96 97 onBumbleLoaded() { 98 this.bumbleLoaded = true; 99 this.requestUpdate(); 100 } 101} 102customElements.define('bumble-controls', BumbleControls); 103