如何使用蓝牙从 Android Wear 直接向 PC 发送传感器数据

How to send sensor data directly to PC from Android Wear using bluetooth

假设我的电脑上有蓝牙加密狗。
如何直接向我的电脑发送数据。
我不想使用 phone 中间人。
(通常在调试 Wear over bluetooth 时使用)
Android Wear 可以直接与PC 配对,然后传输任何数据吗?

您需要对 Android Wear 手表和 phone 上的 Wear App 之间的蓝牙协议进行逆向工程。鉴于 Wear App 用于更新手表上的 OS Wear 软件,Google 可以随时更改协议。因此,虽然您可能能够嗅探流量并复制 Wear 应用程序的行为以便能够与手表对话,但您只需一次更新就可以重新进行逆向工程。

我已经尝试并确认它适用于 Android Wear 5.1(版本 1.1 和最新版本 1.3)。
证明:https://www.youtube.com/watch?v=yyGD8uSjXsI
我不确定 Google 是否会很快修补它,因为它看起来像是一个漏洞。

您需要 android 带 WiFi 的手表,例如 Samsung Gear Live、Moto360、LG Urbane 等。供您参考,LG G Watch 不支持 WiFi。 然后首先您需要将您的手表与您的 phone 配对,然后转到您的手表,启用 WiFi 和 select 任何 WiFi 热点。然后手表会要求您在 phone 上输入密码。之后,它将连接到 WiFi。

那么现在您应该去 android phone,然后取消配对手表。这是因为我们要强制手表直接使用 WiFi 连接。否则它将始终通过 phone 作为中间人使用蓝牙。
您可以通过 运行 和 Android 佩戴浏览器并浏览任何随机页面来仔细检查手表是否正在使用 WiFi。

然后在你的代码中(server/client模型),正常使用套接字即可。
例如,我使用 aysnctask 进行网络连接,如下所示。你应该通过注册侦听器来获取传感器数据,有很多例子所以我不在这里post。

class ConnectServer  extends AsyncTask<Void, Void, Void> {

    public ConnectServer() {
        super();
    }

    @Override
    protected Void doInBackground(Void... params) {
        sendToServer();
        return null;
    }

    public void sendToServer(){
        Socket socket = null;
        BufferedWriter out = null;
        try
        {
            socket = new Socket(IP_ADDRESS, 5000); // IP address of your computer
            out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            while(isSending)
            {
                //x,y,z,w is from android sensor 
                out.write(String.format("%.3f",x)+
                    ","+String.format("%.3f",y)+
                    ","+String.format("%.3f",z)+
                    ","+String.format("%.3f",w)+"/");
                out.flush();
                Thread.sleep(INTERVAL); // 50ms is quite good
            }

            out.close();
            socket.close();
        }
        catch (Exception e)
        {
            Log.e("socket",""+e.toString());
            e.printStackTrace();
        }
        finally
        {
            if (socket != null)
            {
                try
                {
                    socket.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            if (out != null)
            {
                try
                {
                    out.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
}

对于服务器,我在 Unity 中使用 .net Async Socket,但它对于任何 .net 应用程序都应该是相同的。代码没有优化或错误检查彻底,但你明白了。

using UnityEngine;
using System.Collections;
using System;
using System.IO;
using System.Net.Sockets;
using System.Net;
using System.Text;

public class AsyncServer : MonoBehaviour {
    private byte[] data = new byte[1024];
    private int size = 1024;
    private Socket server;
    private Socket client;
    float x, y, z, w;

    void Start () {
        server = new Socket(AddressFamily.InterNetwork,
                  SocketType.Stream, ProtocolType.Tcp);

        IPAddress ipAd = IPAddress.Parse("YOUR IP ADDRESS");
        //IPEndPoint iep = new IPEndPoint(IPAddress.Any, 5000);
        IPEndPoint iep = new IPEndPoint(ipAd, 5000);
        server.Bind(iep);
        server.Listen(5);
        server.BeginAccept(new AsyncCallback(AcceptConn), server);

    }

    void AcceptConn(IAsyncResult iar)
    {
        Socket oldserver = (Socket)iar.AsyncState;
         client = oldserver.EndAccept(iar);
        Debug.Log("Accepted client: " + client.ToString());
        client.BeginReceive(data, 0, size, SocketFlags.None,
            new AsyncCallback(ReceiveData), client);
    }

    void SendData(IAsyncResult iar)
    {
        Socket client = (Socket)iar.AsyncState;
        int sent = client.EndSend(iar);
        client.BeginReceive(data, 0, size, SocketFlags.None,
                    new AsyncCallback(ReceiveData), client);
    }

    void ReceiveData(IAsyncResult iar)
    {
        Socket client = (Socket)iar.AsyncState;
        int recv = client.EndReceive(iar);
        if (recv == 0)
        {
            client.Close();
            Debug.LogError("Waiting for client...");
            server.BeginAccept(new AsyncCallback(AcceptConn), server);
            return;
        }
        string receivedData = Encoding.ASCII.GetString(data, 0, recv);
        //Debug.Log("len: " + recv + ", " + receivedData);

        {
            var s = receivedData.Split(',');
            if (s.Length == 4)
            {
                float xx = float.Parse(s[0]);
                float yy = float.Parse(s[1]);
                float zz = float.Parse(s[2]);
                s[3] = s[3].Replace("/","");
                float ww = float.Parse(s[3]);
                Debug.Log("len: " + recv + ", " + xx + ", " + yy + ", " + zz + ", " + ww);
            } 
        }

        client.BeginReceive(data, 0, size, SocketFlags.None,
            new AsyncCallback(ReceiveData), client);
    }
}