Bluetooth ã¨è¨ãã¨ããã«ãæ¬ãéãããã¯ããã¸ã¼ã§ãããæè¡ãããªãå¤ãã®æ©å¨ã«æ¨æºã§æè¼ãããããã«ãªã£ãä»ããããã£ã¨ããã¤ã¹ãã«ã¨ã£ã¦ Bluetooth ããæé ã«ä½¿ããæãæ¥ãã¨è¨ããã®ã§ã¯ç¡ãã§ããããï¼ç¹ã« USB ã¨éã£ã¦ã³ã¼ããè¦ãããç¡ç· LAN ããè¨å®ãç°¡åãªã®ã§ãã¡ãã£ã¨ããéä¿¡ã«ã¯æé©ã ã¨æãã¾ããæè¿ã® Android ã«ã¯ã ããã Bluetooth ãä»ãã¦ããããã®ã§ãAndroid ã® Bluetooth ã使ããMac ã®ä»®æ³ã·ãªã¢ã«ãã¼ãã«æ¥ç¶ããæ¹æ³ãæ¸ãã¾ããæ¬å½ã¯ iPhone ã§ã試ãããã£ãã®ã§ããã Apple ã¯ç´ 人ã Bluetooth ã使ãæ¹æ³ãæä¾ãã¦ããªãã®ã§è«¦ãã¾ããã
Bluetooth ã¨ã¯ä½ãï¼
ããã°ã©ãããè¦ã¦ãBluetooth ã¯ã ããã TCP/IP ã¨åãããã«æ±ãã¾ããTCP/IP ã¨åãããã¼ã¿ã°ã©ã åéä¿¡ã§ãã L2CAP ã®ä¸ã«ã»ãã·ã§ã³åéä¿¡ã® RFCOMM ãä¹ã£ã¦ãã¦ãRFCOMM ããã®ã¾ã¾ã·ãªã¢ã«ãã¼ãã¨ãã¦ä½¿ããã¨ãåºæ¥ã¾ãã
Bluetooth ã§ããã¼ãçªå·ãããã¾ãããTCP/IP ã¨éããã¼ãã¯åçã«æ±ºã¾ãã¾ãããã¼ããåçã«æ±ºã¾ããªããã®ãã¼ãçªå·ã¯ã©ããã£ã¦è¦ã¤ããã°è¯ãã®ãã¨ããã¨ãæ¬æ°ã§æ¥ç¶ããåã«ã¾ã SDP ã¨ãããã¼ãæ¤ç´¢ãµã¼ãã¹ã使ã£ã¦ãµã¼ãã¹ã¨ãã¼ãçªå·ã¨ã®å¯¾å¿ã調ã¹ã¾ããæ¤ç´¢ãã¼ã«ãªãã®ã¯ Service ID ã¨å¼ã°ãã UUID ã§ãããã¯äºã決ãã¦ããã¾ããã¨ãã訳ã§ãTCP/IP ã¯ã©ã¤ã¢ã³ãã IP ã¢ãã¬ã¹ã¨ãã¼ãçªå·ã使ã£ã¦æ¥ç¶ããã®ã«å¯¾ãã¦ãBluetooth 㯠MAC ã¢ãã¬ã¹ã¨ UUID ã§æ¥ç¶ã試ã¿ã¾ãã
å®éã«ã¯ Bluetooth æ©å¨ã¯è¤æ°ã®éä¿¡çµè·¯ã使ããã¨ãããããã¾ããä¾ãã° Bluetooth ããããã©ã³ã ã¨ãé³å£°ã®çµè·¯ã¨ã¯å¥ã«éä¿¡å質ãã¨ã³ã³ã¼ãã£ã³ã°æ å ±ã®ããåããå¿ è¦ã§ãããã®ããã«ä¸æ¬ã®çµè·¯(ãããã³ã«)ã¨ã¯å¥ã«ãæ©è½ãã¨ã«è¤æ°ã®ãããã³ã«ã®ä½¿ãæ¹ãå®ãããã®ãã¾ã¨ãã¦ãããã¡ã¤ã«ã¨å¼ã³ã¾ãããããã¡ã¤ã«ã«ã¯ä¾ãã°ããããã©ã³ã«ä½¿ã A2DP ãã¯ã¤ã¤ã¬ã¹ãã¦ã¹ã«ä½¿ã HID ãªã©ãããã¾ãã
ãããã¡ã¤ã«ã¯ã¤ã³ã¿ã¼ãããã§è¨ã RFC ã®ãããªãã®ã§ããåç §é¢ä¿ã沢山ãã£ã¦èªã¿ã«ããã®ã§ãæå㯠Serial Port Profile ã®ãããªåç´ãªãã¤ããåå¼·ããã¨è¯ãã§ãããã Android ã® API ã§ã¯ RFCOMM ããæ±ããªãã®ã§ã©ããªãããã¡ã¤ã«ã§ãèªä½åºæ¥ãããã§ã¯ãªãã§ããä¾ãã°ç¡ç·ãã¦ã¹ããã¼ãã¼ãã® HID ãããã¡ã¤ã«ã«ã¯ L2CAP ãè¦ãã®ã§ Java ã§èªä½ããäºã¯åºæ¥ã¾ãããå¤å Android-NDK 㨠C ã使ãã°ä½ããã¨æãã¾ãã
Android 㧠Bluetooth ã使ãæºå
ããã§ã¯ Android ããµã¼ãã¼ã¨ãã¦åãããSPP (Serial Port Profile) çµç±ã§ Mac ã¨æ¥ç¶ãã¦ã¿ã¾ããå®å
¨ãªã½ã¼ã¹ã¯
https://github.com/propella/BTHello/blob/master/src/org/metatoys/bt/BTHelloActivity.java
ã«ããã¾ããAndroid 㧠Bluetooth ã使ãæ¹æ³ã¯ http://developer.android.com/guide/topics/wireless/bluetooth.html ã«è©³ããæ¸ãã¦ããã®ã§ãã®ã¾ã¾çä¼¼ããã°åãã¾ããè¦ç¹ã ãæ¸ãã¨ãã¾ã AndroidManifest.xml å
㧠android.permission.BLUETOOTH ãæå¹ã«ããå¿
è¦ãããã¾ãã
<manifest ... > <uses-permission android:name="android.permission.BLUETOOTH" /> ... </manifest>
ãµã¼ãã¼ã¨ã㦠Bluetooth ã§å¾ ã¡åãã
å ç¨ Bluetooth æ¥ç¶ã«ã¯ Service ID ãå¿ è¦ã ã¨æ¸ãã¾ãããããã§ã¯ SPP ã使ãã¾ãã®ã§ SPP ã§å®ãããã Service ID "00001101-0000-1000-8000-00805F9B34FB" ã使ãã¾ããã¾ããService Name ã¨ããã®ãæå®ãã¦æ¥ç¶ã«é©å½ã«ååãã¤ãã¾ããBluetooth ããã¤ã¹ã¸ã®ã¢ã¯ã»ã¹ã«ã¯ BluetoothAdapter ã使ãã¾ãã
public class BTHelloActivity extends Activity { private static final String TAG = "BTHello"; private static final String SERVICE_NAME = "BTHello"; private static final String SERIAL_PORT_SERVICE_ID = "00001101-0000-1000-8000-00805F9B34FB"; private static final UUID SERVICE_ID = UUID.fromString(SERIAL_PORT_SERVICE_ID); AcceptThread thread; BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Activity ã®æ®ãã®ã³ã¼ãã§ã¯ãåã«èµ·åæã«æ¥ç¶ã¹ã¬ãããç«ã¡ä¸ããåæ¢æã«åé¤ãã¦ãã ãã§ãã
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); thread = new AcceptThread(); thread.start(); } @Override protected void onDestroy () { if (thread != null) { thread.cancel(); } }
å®ç¾©ããå¤ãæå®ãã¦ãµã¼ãã¼ã½ã±ãããä½ãã¾ããAndroid API ã¯å¤§ã¾ãã«åºæ¥ã¦ããã®ã§ listenUsingRfcommWithServiceRecord ã ã㧠SDP ã¸ã®ç»é²ã¨ãµã¼ãã¼ã½ã±ããä½æãåæã«è¡ãã¾ããéã«è¨ãã¨ç´æ¥ãã¼ãçªå·ãæå®ããäºã¯åºæ¥ã¾ããã
private class AcceptThread extends Thread { private BluetoothServerSocket serverSocket; public AcceptThread() { try { serverSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(SERVICE_NAME, SERVICE_ID); } catch (IOException e) { } }
å¾ã¯ TCP ãµã¼ãã¨åãã§ããaccept ã§å¾ ã¡ããããã£ã¦ããæ¥ç¶ã§æ°ããã½ã±ãããä½ãéä¿¡é¨åã«æ¸¡ãã¾ãã
public void run() { BluetoothSocket socket = null; while (true) { try { socket = serverSocket.accept(); } catch (IOException e) { Log.e(TAG, "Fail to accept.", e); break; } Log.d(TAG, "A connection was accepted."); if (socket != null) { connect(socket); } Log.d(TAG, "The session was closed. Listen again."); } }
éä¿¡é¨åã§ã¯åã«ä¸æåæ¥ããã¨ã«ç¾å¨æå»ãè¿ãã¦ãã¾ããããã§ã¯ãµãã£ã¦ã¾ãããæ®éã¯å ¥åã¨åºåã§å¥ã¹ã¬ããã«ããã»ããè¯ãã¨æãã¾ãã
private void connect(BluetoothSocket socket) { DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); try { InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); Log.d(TAG, "Connection established."); out.write("Hello I'm Bluetooth! Press Q to quit.\r\n".getBytes()); while (true) { byte[] buffer = new byte[1024]; int bytes = in.read(buffer); Log.d(TAG, "input =" + new String(buffer, 0, bytes)); out.write((df.format(new Date()) + ": " + new String (buffer, 0, bytes) + "\r\n").getBytes()); if (buffer[0] == 'q') { out.write(("Bye!\r\n").getBytes()); break; } } socket.close(); } catch (IOException e) { Log.e(TAG, "Something bad happened!", e); } }
ã§ãå¾å§æ«ãã¦ããã¾ãã§ãã
/** Will cancel the listening socket, and cause the thread to finish */ public void cancel() { try { serverSocket.close(); Log.d(TAG, "The server socket is closed."); } catch (IOException e) { } } } }
Mac OSX ãã¯ã©ã¤ã¢ã³ãã¨ãã¦ä½¿ã
Mac OSX ã¯æåãã SPP ããµãã¼ããã¦ãã¾ãã®ã§ãå ç¨ä½ã£ã SPP ãã·ãªã¢ã«ãã¼ãã¨ãã¦ç¹ããäºãåºæ¥ã¾ãã
ã¾ã Android å´ã®è¨å®
- ãè¨å®ã-ãç¡ç·ã¨ãããã¯ã¼ã¯ã-ãBluetooth è¨å®ã㧠Bluetooth ã®è¨å®ç»é¢ãéãã¾ã
- ãBluetoothã ã®ãã§ãã¯ãæå¹ã§ããäºã確èªãã¾ãã
- ãæ¤åºå¯è½ããã§ãã¯ãæå¹ã«ãã¾ãã
Mac å´ã¯ã¡ãã£ã¨ãããããã§ããã·ã¹ãã ããªãã¡ã¬ã³ã¹ã® Bluetooth ãéãã+ ãã¿ã³ãæ¼ãã¦ãã°ããå¾ ã¤ã¨ãAndroid ã®ååãç¾ããã®ã§é¸æãã¾ãã
ãããããã¢è¨å®ã®ç»é¢ãåºãã®ã§ãAndroid å´ã確èªãã¦ããã¢è¨å®ããæ¼ãã¾ãã
çµæãã¤ã¢ãã°ãéããã¨ãå ã»ã©ã® Bluetooth è¨å®ç»é¢ã« Android ãç¾ãã¦ãã¾ãã®ã§é¸æããä¸ã®å°ããªæ¯è»ãã¿ã³ã®ä¸ã® ãEdit Serial Ports...ããé¸ã³ã¾ãã
ãã㨠å ã»ã©ã® SERVICE_NAME ã§æå®ããååã«ã¡ãªãã ã·ãªã¢ã«ãã¼ãåãä½ããã¾ãããããç¾ããªãæã¯ãã®ç»é¢ã§ + ãæ¼ãã¨åºã¦ããã®ã§ Apply ãã¦æºåå®äºã§ãã
Bluetooth ã·ãªã¢ã«ãã¼ããå®é¨
Mac ã®ã¿ã¼ããã«ãåºã
$ sudo screen /dev/tty.N-04D-BTHello
ã®ããã«ãã¦å ç¨ç¾ããã·ãªã¢ã«ãã¼ãã screen ã³ãã³ãã§æå®ãã㨠Bluetooth ã«æ¥ç¶åºæ¥ã¾ããã¾ããã®ããã©ã ã¯åã«ãã¼å ¥åãã¨ã«æå»ã表示ããã ãã§ãã
çµäºå¾ãããã¿ã¼ããã«ãçã£ãã
$ stty sane
ã¨ãã£ã¦ä¸ããããã¦ãçµæ§é¢ç½ãå¿ç¨ãããããã§ãããï¼