I tried to summarize the general procedure when connecting bluetooth to Raspberry Pi from a smartphone / PC and performing control using python on the Raspberry Pi side. (Since I was referring to an outside site and I got stuck in some places ...)
reference: https://qiita.com/shippokun/items/0953160607833077163f
#Install pyBluez dependent packages
$ sudo apt-get install -y python-dev libbluetooth3-dev
#Install pyBluez
$ sudo pip3 install pybluez
# sudo apt-get install bluetooth blueman -y # bluez-tool
$ sudo apt install libusb-dev
$ sudo apt install libdbus-1-dev
$ sudo apt install libglib2.0-dev
$ sudo apt install libudev-dev -y
$ sudo apt install libical-dev -y
$ sudo apt install libreadline-dev -y
$ sudo apt install libdbus-glib-1-dev -y
$ sudo apt install libbluetooth-dev
$ hciconfig
hci0: Type: Primary Bus: UART
BD Address: DC:A6:32:37:3D:60 ACL MTU: 1021:8 SCO MTU: 64:1
UP RUNNING PSCAN
RX bytes:3163 acl:22 sco:0 events:92 errors:0
TX bytes:3627 acl:21 sco:0 commands:64 errors:0
$ sudo sdptool browse local | grep Channel
Channel: 17
Channel: 16
Channel: 15
Channel: 14
Channel: 10
Channel: 9
Channel: 24
Channel: 12
Channel: 3
Just run sudo sdptool browse local and you'll see what channel is being used for what.
$ sudo sdptool browse local
...
Service Name: Headset Voice gateway
Service RecHandle: 0x10005
Service Class ID List:
"Headset Audio Gateway" (0x1112)
"Generic Audio" (0x1203)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 12
Profile Descriptor List:
"Headset" (0x1108)
Version: 0x0102
...
Add serial port service by specifying an unused channel. (Of course, if you specify a used channel, it will fail in the next step. I didn't notice this and got it first ...)
sudo sdptool add --channel=22 SP
If you want to add a serial port service without specifying a channel, do the following instead of the above:
sudo sdptool add SP
Check if the serial port service could be added.
sudo sdptool browse local
When the above is executed, it looks like the following Service Name: Serial Port You should get the output. here Channel: 1 The channel number is displayed as shown, so check it.
Service Name: Serial Port
Service Description: COM Port
Service Provider: BlueZ
Service RecHandle: 0x10001
Service Class ID List:
"Serial Port" (0x1101)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 1
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
Profile Descriptor List:
"Serial Port" (0x1101)
Version: 0x0100
sudo nano /etc/systemd/system/dbus-org.bluez.service
Add --compat to the ExecStart ... line (make it work in compatibility mode). Also,
ExecStartPost=/usr/bin/sdptool add SP
#When specifying a channel, describe the following instead of the above.
#Be careful not to specify used channels.
# ExecStartPost=/usr/bin/sdptool add --channel=22 SP
Is added so that the serial communication protocol (SPP) is added at startup. Specifying the channel number is optional.
[Unit]
Description=Bluetooth service
Documentation=man:bluetoothd(8)
ConditionPathIsDirectory=/sys/class/bluetooth
[Service]
Type=dbus
BusName=org.bluez
ExecStart=/usr/lib/bluetooth/bluetoothd --compat
ExecStartPost=/usr/bin/sdptool add SP
#When specifying a channel, describe the following instead of the above.
#Be careful not to specify used channels.
# ExecStartPost=/usr/bin/sdptool add --channel=22 SP
NotifyAccess=main
#WatchdogSec=10
#Restart=on-failure
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
LimitNPROC=1
ProtectHome=true
ProtectSystem=full
Restart the Raspberry Pi.
$ sudo reboot -h
Turn on Bluetooth on the Raspberry Pi and allow Bluetooth to be searched on the server side.
sudo bluetoothctl
[bluetooth] power on
[bluetooth] discoverable on
[bluetooth] agent on
[bluetooth] default-agent
If you try to connect in this state, you will be asked to confirm the passkey and service authentication as shown below, so enter yes / no.
reference: https://qiita.com/oko1977/items/9f53f3b11a1b033219ea
[CHG] Device 80:19:34:31:CD:1E Connected: yes
Request confirmation
[agent] Confirm passkey 291086 (yes/no): yes
Authorize service
[agent] Authorize service 0000110e-0000-1000-8000-00805f9b34fb (yes/no): yes
Authorize service
[agent] Authorize service 0000110d-0000-1000-8000-00805f9b34fb (yes/no): yes
[CHG] Device 80:19:34:31:CD:1E UUIDs: 00001000-0000-1000-8000-00805f9b34fb
...
[CHG] Device 80:19:34:31:CD:1E UUIDs: c7f94713-891e-496a-a0e7-983a0946126e
[CHG] Device 80:19:34:31:CD:1E Connected: no
[CHG] Device 80:19:34:31:CD:1E Connected: yes
[CHG] Device 80:19:34:31:CD:1E Connected: no
[bluetooth]#
here,
If it is recognized as a sound device as shown in the image above, select raspberrypi from the device and printer and select
--Serial Port (SPP)'SerialPort' --Remotely controllable devices --Remote control
Uncheck items other than. (If you do not remove it, it will be treated as a sound device. In my environment, the sound device I was using was inactivated and no sound was produced.)
By the way, if "Serial Port (SPP)'SerialPort'" does not appear, follow the procedure at the beginning. sdptool add SP To check again if the serial communication service is enabled.
Do the following:
sudo rfcomm listen /dev/rfcomm0
To specify the channel number, execute as follows (in the case of channel number 22).
sudo rfcomm listen /dev/rfcomm0 22
Launch another console and cat / dev / rfcomm0 to check the message on the Raspberry Pi side.
$ sudo cat /dev/rfcomm0
Also, launch another console Try echoing the message to the / dev / rfcomm0 device on the Raspberry Pi.
$ sudo echo abcd > /dev/rfcomm0
1 # -*- coding: utf-8 -*-
2 # Author: Shinsuke Ogata
3
4 import sys
5 import traceback
6 import time
7 import bluetooth
8 import threading
9
10 class SocketThread(threading.Thread):
11 '''
12 @param client_Client socket returned as a result of socket accept.
13 @param notify_receive Functions / methods that process data received by serial communication.
14 @param notify_error Function / method that executes processing when an error occurs
15 '''
16 def __init__(self, server_socket, client_socket, notify_receive, notify_error, debug):
17 super(SocketThread, self).__init__()
18 self._server_socket = server_socket
19 self._client_socket = client_socket
20 self._receive = notify_receive
21 self._error = notify_error
22 self._debug = debug
23
24 def run(self):
25 while True:
26 try:
27 data = self._client_socket.recv(1024)
28 if self._receive != None:
29 self._receive(data)
30 except KeyboardInterrupt:
31 self._client_socket.close()
32 self._server_socket.close()
33 break
34 except bluetooth.btcommon.BluetoothError:
35 self._client_socket.close()
36 self._server_socket.close()
37 if self._debug:
38 print('>>>> bluetooth.btcommon.BluetoothError >>>>')
39 traceback.print_exc()
40 print('<<<< bluetooth.btcommon.BluetoothError <<<<')
41 break
42 except:
43 self._client_socket.close()
44 self._server_socket.close()
45 if self._debug:
46 print('>>>> Unknown Error >>>>')
47 traceback.print_exc()
48 print('<<<< Unknown Error <<<<')
49 break
50
51 class BluetoothServer(threading.Thread):
52
53 '''
54 @param notify_receive Functions / methods that process data received by serial communication.
55 @param notify_error Function / method that executes processing when an error occurs
56 @param debug Set to True when issuing debug messages
57 '''
58 def __init__(self, notify_receive, notify_error=None, debug=False):
59 super(BluetoothServer, self).__init__()
60 self._port =1
61 self._receive = notify_receive
62 self._error = notify_error
63 self._server_socket = None
64 self._debug = debug
65
66 def run(self):
67 try:
68 self._server_socket=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
69
70 if self._debug:
71 print("BluetoothServer: binding...")
72
73 self._server_socket.bind( ("",self._port ))
74
75 if self._debug:
76 print("BluetoothServer: listening...")
77
78 self._server_socket.listen(1)
79
80 client_socket,address = self._server_socket.accept()
81
82 if self._debug:
83 print("BluetoothServer: accept!!")
84 task = SocketThread(self._server_socket, client_socket, self._receive, self._error, self._debug)
85 task.start()
86 except KeyboardInterrupt:
87 if self._debug:
88 print("BluetoothServer: KeyboardInterrupt")
89 except:
90 if self._debug:
91 print('>>>> Unknown Error >>>>')
92 traceback.print_exc()
93 print('<<<< Unknown Error <<<<')
94
95
96 def receive(data):
97 print("receive [%s]" % data)
98
99 def error(data):
100 print("error")
101
102 if __name__ == '__main__':
103 task = BluetoothServer(receive, error, True)
104 task.start()
Recommended Posts