在PC上,将Android客户端与Python服务器初始化蓝牙连接

16

我正在尝试从我的安卓手机(三星Galaxy S2)向运行Linux的PC上的Python脚本发送“helloWorld”(仅为字符串),但无法使其正常工作。以下是安卓应用程序(客户端)和Python脚本(服务器端)的代码。PC和手机上的蓝牙都可以正常工作(例如,我可以通过蓝牙从手机发送照片)。在下面的Java代码中调用btSocket.connect();时,它就不能连接。我是否需要指定要连接的端口,因为我已经为serverSocket指定了端口?任何帮助将不胜感激。

public class BlueTooth_testActivity extends Activity {
    TextView header;
    Button discoverDevicesBtn;
    Button sendMsgBtn;
    Button closeBtn;
    EditText sendTxt;
    BluetoothAdapter btAdapter;
    BluetoothSocket btSocket;
    private static String btAdress = "00:10:60:D1:95:CD";
    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    private OutputStream out;
    public BluetoothDevice device;
    private Boolean CONNECTED = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //init layout parameters        
        header = (TextView) findViewById(R.id.text1);
        discoverDevicesBtn = (Button) findViewById(R.id.discBtn);
        sendMsgBtn = (Button) findViewById(R.id.sendButton);
        closeBtn = (Button) findViewById(R.id.closeButton);
        sendTxt = (EditText) findViewById(R.id.editText1);
        discoverDevicesBtn.setOnClickListener(discoverDeviceListener);
        sendMsgBtn.setOnClickListener(sendMsgListener);
        closeBtn.setOnClickListener(closeBtnListener);
        //init bluetooth
        btAdapter = BluetoothAdapter.getDefaultAdapter();
        if (btAdapter.isEnabled()) {
            Toast.makeText(this, "Bluetooth state:" + btAdapter.getState() + " Ok!", Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(this, "Bluetooth state:" + btAdapter.getState() + " Not ok!", Toast.LENGTH_LONG).show();
        }

    }

    private Button.OnClickListener discoverDeviceListener = new Button.OnClickListener() {@Override
        public void onClick(View v) {
            if (!CONNECTED) {
                device = btAdapter.getRemoteDevice(btAdress);
                header.append("\nRemote device: " + device.getName());
                try {
                    btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
                } catch (Exception e) {
                                    }
                header.append("\n createRfcommsockettoservice! ");
                btAdapter.cancelDiscovery();
                try {
                    btSocket.connect();
                    CONNECTED = true;
                    header.append("\n btSocket Created!");
                } catch (IOException e) {
                    Toast.makeText(getApplicationContext(), "Could not connect to socket", Toast.LENGTH_LONG);
                    try {
                        btSocket.close();
                    } catch (Exception b) {}
                }
            }

        }
    };


    private Button.OnClickListener sendMsgListener = new Button.OnClickListener() {@Override
        public void onClick(View v) {
            if (CONNECTED) {
                try {
                    out = btSocket.getOutputStream();
                    String msg = sendTxt.getText().toString();
                    byte[] msgBffr = msg.getBytes();
                    out.write(msgBffr);
                    Toast.makeText(getApplicationContext(), "Message sent", Toast.LENGTH_LONG).show();
                } catch (Exception a) {
                    Toast.makeText(getApplicationContext(), "Could not send msg", Toast.LENGTH_LONG).show();
                }
            } else {
                Toast.makeText(getApplicationContext(), "cant send msg, not connected", Toast.LENGTH_LONG).show();
            }

        }
    };


}  

(由于问题在连接设置中某处,我没有费心包含Java代码的其余部分)

import bluetooth

name="bt_server"
target_name="siggen"
uuid="00001101-0000-1000-8000-00805F9B34FB"

def runServer():
serverSocket=bluetooth.BluetoothSocket(bluetooth.RFCOMM )
    port=bluetooth.PORT_ANY
    serverSocket.bind(("",port))
    print "Listening for connections on port: ", port   
    serverSocket.listen(1)
    port=serverSocket.getsockname()[1]
    inputSocket, address=serverSocket.accept()
    print "Got connection with" , address
    data=inputSocket.recv("1024")
    print "received [%s] \n " % data    
    inputSocket.close()
    serverSocket.close()  

runServer()  

.


这里使用Wireshark捕获是否有帮助? - James
3
你已经缩小问题范围,确定问题是出在 Python 还是 Java 中了吗? - notbad.jpeg
2
你应该始终通过尝试将你的客户端/服务器与一款经过验证的软件配合使用来测试客户端/服务器实现。尝试获取一个在应用商店中评分较高的蓝牙应用程序,并尝试连接到你的Python脚本。然后,尝试获取一个质量上乘的Python服务器,以便连接到你的Android应用程序。然后查看你的脚本是否能够连接到你的Android应用程序。 - Alex W
我还没有找到一个通用的蓝牙客户端或服务器应用程序来测试我的相应应用程序(将在有时间时尝试寻找)。无论如何,感谢您的提示。我还没有成功设置我的Wireshark以捕获蓝牙流量。 - Simen Andresen
3个回答

1

根据已发布的建议,以下是我如何使您的代码按照您所期望的方式工作:

   

import bluetooth
    
    name="bt_server"
    target_name="test"
    # some random uuid, generated by https://www.famkruithof.net/uuid/uuidgen
    uuid="0fee0450-e95f-11e5-a837-0800200c9a66"
    
    def runServer():
        # you had indentation problems on this line:
        serverSocket=bluetooth.BluetoothSocket(bluetooth.RFCOMM )
        port=bluetooth.PORT_ANY
        serverSocket.bind(("",port))
        print "Listening for connections on port: ", port   

        # wait for a message to be sent to this socket only once
        serverSocket.listen(1)
        port=serverSocket.getsockname()[1]
    
        # you were 90% there, just needed to use the pyBluez command:
        bluetooth.advertise_service( serverSocket, "SampleServer",
                           service_id = uuid,
                           service_classes = [ uuid, bluetooth.SERIAL_PORT_CLASS ],
                           profiles = [ bluetooth.SERIAL_PORT_PROFILE ] 
                            )
    
        inputSocket, address=serverSocket.accept()
        print "Got connection with" , address
        data=inputSocket.recv(1024)
        print "received [%s] \n " % data    
        inputSocket.close()
        serverSocket.close()  
    
    runServer()  

在命令行中运行该代码,它将永远等待直到通过蓝牙发送消息。因此,在运行该代码的同时,您只需通过蓝牙连接您的Android设备,然后使用您开发的Android应用程序方法或类似于我使用的https://gist.github.com/tito/7432757的方法发送数据(参考与上述相同的uuid)。

1

您不需要指定端口,它应该只会将您连接到第一个开放的RFComm通道。我发现对于我制作的蓝牙应用程序,为了让它在我的手机上工作,我必须在尝试在应用程序中连接之前手动连接到运行服务器的计算机。也就是说,我要通过设置->无线/网络->蓝牙设置-><查找/配对电脑>进行所有操作,直到通知在系统托盘中弹出。然后,当我尝试通过我的应用程序进行套接字连接时,它就可以工作了。我觉得这很奇怪,因为我只需要在手机上跳过这些步骤,而不需要在平板电脑上跳过,所以可能取决于设备。

此外,您需要在单独的线程中执行连接操作。


似乎Python脚本中的serverSocket如果不绑定到特定端口就无法监听或连接。我已经将设备配对并成功地从我的Galaxy SII手机通过Blueman传输文件到我的Linux电脑,但仍然无法连接应用程序。 - Simen Andresen

1

服务器部分

当涉及到Python时,我感到有些力不从心,但是看起来您的Python片段没有使用uuid。例如,pybluez存储库中有一个示例服务器,在调用advertise_service时使用了uuid,而您的片段似乎没有。如果您想要类似的效果,您的代码片段可能如下所示:

import bluetooth

name="bt_server"
target_name="siggen"
uuid="00001101-0000-1000-8000-00805F9B34FB"

def runServer():
serverSocket=bluetooth.BluetoothSocket(bluetooth.RFCOMM )
    port=bluetooth.PORT_ANY
    serverSocket.bind(("",port))
    print "Listening for connections on port: ", port   
    serverSocket.listen(1)
    port=serverSocket.getsockname()[1]

    #the missing piece
    advertise_service( server_sock, "SampleServer",
                       service_id = uuid,
                       service_classes = [ uuid, bluetooth.SERIAL_PORT_CLASS ],
                       profiles = [ bluetooth.SERIAL_PORT_PROFILE ] 
                        )

    inputSocket, address=serverSocket.accept()
    print "Got connection with" , address
    data=inputSocket.recv("1024")
    print "received [%s] \n " % data    
    inputSocket.close()
    serverSocket.close()  

runServer()  

客户端

BluetoothDevice.createRfcommSocketToServiceRecord() 用于创建“安全通信套接字”。你的服务器是否在做这个?如果不是,也许 BluetoothDevice.createInsecureRfcommSocketToServiceRecord() 是适当的调用?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接