1<html data-bs-theme="dark">
2
3<head>
4    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
5        integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
6</head>
7
8<body>
9    <nav class="navbar navbar-dark bg-primary">
10        <div class="container">
11            <span class="navbar-brand mb-0 h1">Bumble Handsfree</span>
12        </div>
13    </nav>
14    <br>
15
16    <div class="container">
17
18        <label class="form-label">Server Port</label>
19        <div class="input-group mb-3">
20            <input type="text" class="form-control" aria-label="Port Number" value="8989" id="port">
21            <button class="btn btn-primary" type="button" onclick="connect()">Connect</button>
22        </div>
23
24        <label class="form-label">Dial Phone Number</label>
25        <div class="input-group mb-3">
26            <input type="text" class="form-control" placeholder="Phone Number" aria-label="Phone Number"
27                id="dial_number">
28            <button class="btn btn-primary" type="button"
29                onclick="send_at_command(`ATD${dialNumberInput.value}`)">Dial</button>
30        </div>
31
32        <label class="form-label">Send AT Command</label>
33        <div class="input-group mb-3">
34            <input type="text" class="form-control" placeholder="AT Command" aria-label="AT command" id="at_command">
35            <button class="btn btn-primary" type="button"
36                onclick="send_at_command(document.getElementById('at_command').value)">Send</button>
37        </div>
38
39        <div class="row">
40            <div class="col-auto">
41                <label class="form-label">Battery Level</label>
42                <div class="input-group mb-3">
43                    <input type="text" class="form-control" placeholder="0 - 100" aria-label="Battery Level"
44                        id="battery_level">
45                    <button class="btn btn-primary" type="button"
46                        onclick="send_at_command(`AT+BIEV=2,${document.getElementById('battery_level').value}`)">Set</button>
47                </div>
48            </div>
49            <div class="col-auto">
50                <label class="form-label">Speaker Volume</label>
51                <div class="input-group mb-3 col-auto">
52                    <input type="text" class="form-control" placeholder="0 - 15" aria-label="Speaker Volume"
53                        id="speaker_volume">
54                    <button class="btn btn-primary" type="button"
55                        onclick="send_at_command(`AT+VGS=${document.getElementById('speaker_volume').value}`)">Set</button>
56                </div>
57            </div>
58            <div class="col-auto">
59                <label class="form-label">Mic Volume</label>
60                <div class="input-group mb-3 col-auto">
61                    <input type="text" class="form-control" placeholder="0 - 15" aria-label="Mic Volume"
62                        id="mic_volume">
63                    <button class="btn btn-primary" type="button"
64                        onclick="send_at_command(`AT+VGM=${document.getElementById('mic_volume').value}`)">Set</button>
65                </div>
66            </div>
67        </div>
68
69        <button class="btn btn-primary" onclick="send_at_command('ATA')">Answer</button>
70        <button class="btn btn-primary" onclick="send_at_command('AT+CHUP')">Hang Up</button>
71        <button class="btn btn-primary" onclick="send_at_command('AT+BLDN')">Redial</button>
72        <button class="btn btn-primary" onclick="send({ type: 'query_call'})">Get Call Status</button>
73
74        <br><br>
75
76        <button class="btn btn-primary" onclick="send_at_command('AT+BVRA=1')">Start Voice Assistant</button>
77        <button class="btn btn-primary" onclick="send_at_command('AT+BVRA=0')">Stop Voice Assistant</button>
78
79        <hr>
80
81        <div id="socketStateContainer" class="bg-body-tertiary p-3 rounded-2">
82            <h3>Log</h3>
83            <code id="log" style="white-space: pre-line;"></code>
84        </div>
85    </div>
86
87
88    <script>
89        let portInput = document.getElementById("port")
90        let atCommandInput = document.getElementById("at_command")
91        let log = document.getElementById("log")
92        let socket
93
94        function connect() {
95            socket = new WebSocket(`ws://localhost:${portInput.value}`);
96            socket.onopen = _ => {
97                log.textContent += 'OPEN\n'
98            }
99            socket.onclose = _ => {
100                log.textContent += 'CLOSED\n'
101            }
102            socket.onerror = (error) => {
103                log.textContent += 'ERROR\n'
104                console.log(`ERROR: ${error}`)
105            }
106            socket.onmessage = (event) => {
107                log.textContent += `<-- ${event.data}\n`
108                let volume_state = JSON.parse(event.data)
109                volumeSetting.value = volume_state.volume_setting
110                changeCounter.value = volume_state.change_counter
111                muted.checked = volume_state.muted ? true : false
112            }
113        }
114
115        function send(message) {
116            if (socket && socket.readyState == WebSocket.OPEN) {
117                let jsonMessage = JSON.stringify(message)
118                log.textContent += `--> ${jsonMessage}\n`
119                socket.send(jsonMessage)
120            } else {
121                log.textContent += 'NOT CONNECTED\n'
122            }
123        }
124
125        function send_at_command(command) {
126            send({ type: 'at_command', 'command': command })
127        }
128    </script>
129    </div>
130</body>
131
132</html>