The fourth experiment in this Raspberry Pi series grew out of a short list of Bluetooth commands encountered while reading another article:
sudo bluetoothctl; power on scan on agent on pair MAC trust MAC connect MAC
The commands were easy enough to remember, but remembering them was not much use without a practical situation in which to try them. A Bluetooth speaker provided a suitable test: route the Raspberry Pi's audio stream to the speaker, then add a physical button that could connect or disconnect the speaker—or, in practice, control whether its audio was muted.
Using the desktop through VNC
The Raspberry Pi is not limited to a text-only terminal. For visual operation, a VNC server can be installed and started as follows:
```# 给板子装客户端 sudo apt-get install tightvncserver
开启一个 VNC 流,代号为 1
tightvncserver :1```
After installing a VNC Viewer client on a Mac, connect to IP:1, replacing IP with the Raspberry Pi's address:

For this series, visual operation is kept to a minimum. The board's performance is limited, and running an additional graphical desktop makes the system noticeably sluggish. The command line is usually more practical for this kind of experiment.
Pairing the speaker from the desktop
For those who prefer a graphical interface, a Bluetooth management tool can be installed with:
sudo apt-get install pi-bluetooth blueman
Once installation is complete, open Preferences -> Bluetooth Manager to view the available Bluetooth devices:

At that point, it is possible to open a browser, play music online, and expect the sound to come from the speaker. However, connecting the device alone does not necessarily select it as the active audio output.
Right-click the volume control to open the list of available outputs:
Anlogsends audio through the headphone jack. Plugging headphones into the board produces sound, although the quality is relatively poor.HDMIis the HDMI output option.- The entries below represent connected Bluetooth devices. The appropriate Bluetooth device must be selected before it can play audio.
Even after selecting the Bluetooth device from that list, there may still be no sound. The exact cause was not investigated, but selecting the corresponding device in the first tab of the volume control panel resolved the problem:

When Bluetooth audio disappears
While working with the GPIO pins, the sound stopped working again. After trying several approaches, the following sequence repeatedly restored the audio connection:
```# 先把 GPIO 引脚上的线给拔了,不拔可能会影响蓝牙驱动的加载?不知道,先拔了
如果之前插着线,重启,重新加载驱动
sudo reboot
再看看是否有报错,比如 Sap driver initialization failed.
service bluetooth status
如果有错误,重新启动下,可以选择 root
service bluetooth restart
然后重新连接蓝牙,一般声音就来了```
The GPIO wiring was removed first, because it seemed possible that it interfered with Bluetooth driver loading. If the wiring had already been connected, the board was rebooted to reload the driver. Checking the Bluetooth service then showed whether an error such as Sap driver initialization failed. had occurred. Restarting the service and reconnecting the speaker generally brought the sound back.
It was never established whether the underlying problem came from driver loading in the Linux kernel or from something else. For this small experiment, the workaround was sufficient.
Adding a hardware control
The next step was to add an external switch. The switch was intended to control the external speaker's audio state—turning the sound on or muting it:

When switch S1 is pressed down, LED1 lights up and the signal at point S, connected to PIN12/GPIO18, becomes low. Reading the signal on P12 is therefore enough to determine the switch state. The test program was:
const execSync = require('child_process').execSync;
const Gpio = require('rpio2').Gpio;
// 初始化 PIN12
const button = new Gpio(12);
button.open(Gpio.INPUT);
button.on('rising', () => {
execSync('pactl set-sink-volume 1 100%');
console.log('open sound');
});
button.on('falling', () => {
execSync('pactl set-sink-volume 1 0%');
console.log('mute');
});
process.on("SIGINT", () => {
button.close();
console.log('shutdown!');
process.exit(0);
});
The implementation is far from elegant, but the basic idea is straightforward: on a rising edge, set the sink volume to 100 percent; on a falling edge, set it to zero.
In practice, the code was not as reliable as it looked. Whether the problem belonged to the operating system or to the rpio2 library was unclear, but the board frequently crashed while handling rising- and falling-edge events. That issue would require a more careful investigation before this could be considered a dependable controller.
After several hours of connecting, disconnecting, rebooting, and testing, the experimental toy was working. It would not be useful in everyday life because the setup was too crude. A further challenge was also considered: detect multiple button presses and perform different actions according to the number of clicks. The resulting program caused the system to crash whenever the button was pressed, so that line of experimentation was abandoned for the time being.