今回は、Microbitとラズパイの間をBluetooth経由で通信するためのサーバーを作成し始めようと思います。
参考にするページは本家Oracleのページです。
元々のやりたいこと
一応この実装の目的は、Microbitからのbluetooth経由メッセージをラズパイで受信して、Midiメッセージを音源モジュールに送信、音を鳴らすというのが目的です。下はイメージになります。
SDPで通信
SDP(Sockets Direct Protocol)はMicrobitとラズパイの通信で使用できるという情報を得て、現在に至りますが、早い話が、Bluetoothでの通信時にこのSDPが使用できるということです。このテクノロジーを使用するためにサポートされて(JDKに入って)いるクラスは下に記載しました。(参考サイト参照)
java.net
packageSocket
ServerSocket
java.nio.channels
package:SocketChannel
ServerSocketChannel
AsynchronousSocketChannel
AsynchronousServerSocketChannel
必要な作業
こんな感じの作業が必要になると思いますが、如何せんやってみないことには始まらないので。。。
SDPサーバーを作る
SDP構成ファイルの作成このページを読んでみると、構成ファイル(設定ファイル)を作る必要がある、と記載しているのでその通りにやってみます。。。
しかし、記載ルールが書いてあるだけなのでよくわからない状態です。
わからないので調べます。そして、ちょうど良いのがありました。設定ファイルのテンプレートのようなものらしいです。早速失敬して。。。
ご丁寧に、全部コメントアウトされています。必要な部分を修正、コメントを外して使用します。
設定ファイル(Conf File)
# # Configuration file to enable InfiniBand Sockets Direct Protocol. # # Each line that does not start with a comment (#) is a rule to indicate when # the SDP transport protocol should be used. The format of a rule is as follows: # ("bind"|"connect") 1*LWSP-char (hostname|ipaddress["/"prefix]) 1*LWSP-char ("*"|port)["-"("*"|port)] # # A "bind" rule indicates that the SDP protocol transport should be used when # a TCP socket binds to an address/port that matches the rule. A "connect" rule # indicates that the SDP protocol transport should be used when an unbound # TCP socket attempts to connect to an address/port that matches the rule. # Addresses may be specified as hostnames or literal Internet Protocol (IP) # addresses. When a literal IP address is used then a prefix length may be used # to indicate the number of bits for matching (useful when a block of addresses # or subnet is allocated to the InfiniBand fabric). # Use SDP for all sockets that bind to specific local addresses #bind 192.168.4.1 * #bind fe80::21b:24ff:fe3d:7896 * # Use SDP for all sockets that bind to the wildcard address in a port range #bind 0.0.0.0 5000-5999 #bind ::0 5000-5999 # Use SDP when connecting to all application services on 192.168.1.* #connect 192.168.1.0/24 1024-* # Use SDP when connecting to the http server or MySQL database on hpccluster. #connect hpccluster.foo.com 80 #connect hpccluster.foo.com 3306
Socketの実装
以前作成したものですが、これに設定ファイルを適用すればいけるみたいです。下のものはSocketサーバーを起動するコードです。
クライアントから送信されたメッセージ(テキストなど)をそのまま返す処理になっています。
public void startServer() { try { System.out.println("*** SocketServer start " + server.isBound() + "***"); Socket recieve = server.accept(); System.out.println("*** Server Get Request start***"); // 受信データの読み込み StringBuilder responseTxt = new StringBuilder(""); // 受信状態 System.out.println("クライアント: " + recieve.getRemoteSocketAddress()); System.out.println("接続: " + recieve.isConnected()); System.out.println("入力ストリームが閉じている: " + recieve.isInputShutdown()); // 受信したリクエスト InputStream in = recieve.getInputStream(); // 返却するレスポンス OutputStream writer = recieve.getOutputStream(); System.out.print("Server recieve is ..."); int c = 0; // CRとCRLFの場合で入力が終了している時がある while((c = in.read()) != -1) { char ch = (char)c; responseTxt.append(ch); // 空の場合 if (c == 10 || c == 13) { break; } } System.out.println(responseTxt.toString()); System.out.println("*** Server Send Response start***"); // レスポンス送信 writer.write((responseTxt.toString() + System.getProperty("file.separator")).getBytes()); writer.flush(); in.close(); writer.close(); System.out.println("*** SocketServer end ***"); } catch (IOException e) { e.printStackTrace(); } finally { // 開いたストリームを閉じる try { closeServer(); } catch (IOException e) { e.printStackTrace(); } } }
一度書けばどこでも動くの精神
ということです(笑)
あとは動かしてみてうまくいくかどうか?を確認します。
そして、これをベースにして「〜を受信したときに〜する」というような処理を実装していきます。
ソースはGithubにコミットしてありますので、よかったら全体のソースも見てみてください、
でわでわ。。。