ラズパイ 無線LANアクセスポイント化


20160610_wlan_ap

ラズパイを 無線LANアクセスポイント 化します。

準備するもの
無線LANの親機になるドングル
BUFFALO WLI-UC-GNM を使用しました

手順は大きく4つです
(1) 無線LANを固定IPアドレスにする
(2) DHCPサーバーの構築
(3) アクセスポイントデーモンの構築
(4) イーサネットと無線LANのルーティングの設定

無線LANのIPアドレスを 192.168.42.1 にして、192.168.42.10 から 192.168.42.50 まで配布するようにします。
有線LAN側のゲートウェイが 192.168.1.1 とします。

作成や変更したファイルは Github で公開しています

(1) 無線LANを固定IPアドレスにする
/etc/network/interfaces を変更する

# 下記のようにコメントにする
#allow-hotplug wlan0
#iface wlan0 inet manual
#    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
#allow-hotplug wlan1
#iface wlan1 inet manual
#    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

# 下記を追加する
allow-hotplug wlan0
iface wlan0 inet static
address 192.168.42.1
netmask 255.255.255.0
gateway 192.168.1.1

(2) DHCPサーバーの構築
DHCP サーバーとして isc-dhcp-server をインストールする

$ sudo apt-get install isc-dhcp-server

/etc/dhcp/dhcpd.conf を変更する

# 下記のようにコメントにする
#option domain-name "example.org";
#option domain-name-servers ns1.example.org, ns2.example.org;

# 下記のコメントを外す
#authoritative;
authoritative;

# 下記を追加する
subnet 192.168.42.0 netmask 255.255.255.0 {
  range 192.168.42.10 192.168.42.50;
  option broadcast-address 192.168.42.255;
  option routers 192.168.42.1;
  default-lease-time 600;
  max-lease-time 7200;
  option domain-name "local";
  option domain-name-servers 8.8.8.8,8.8.4.4;
}

/etc/default/isc-dhcp-server を変更する

# 下記のように変更する
#INTERFACES=""
INTERFACES="wlan0"

(3) アクセスポイントデーモンの構築
hostapd をインストールする

$ sudo apt-get install hostapd

/etc/default/hostapd を変更する

# 下記のように変更する
#DAEMON_CONF=""
DAEMON_CONF="/etc/hostapd/hostapd.conf"

/etc/hostapd/hostapd.conf を作成する

interface=wlan0
driver=nl80211
ssid=fablab_raspi
hw_mode=g
channel=6
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=0456649009
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

(4) イーサネットと無線LANのルーティングの設定
/etc/sysctl.conf を変更する

# 下記のコメントを外す
#net.ipv4.ip_forward=1
net.ipv4.ip_forward=1

iptables コマンドで /etc/iptables.ipv4.nat を作成する

$ sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
$ sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
$ sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
iptables
$ sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"

/etc/network/interfaces を変更する

# 下記を追加する
pre-up iptables-restore < /etc/iptables.ipv4.nat

確認
再起動する

$ sudo reboot

dhcpd が起動している

$ ps auxw | grep dhcpd
root       649  0.0  0.8  10476  7928 ?        Ss   23:06   0:00 /usr/sbin/dhcpd -q -cf /etc/dhcp/dhcpd.conf -pf /var/run/dhcpd.pid wlan0

hostapd が起動している

$  ps auxw | grep hostapd
root       692  0.2  0.3   5920  2996 ?        Ss   23:06   0:01 /usr/sbin/hostapd -B -P /run/hostapd.pid /etc/hostapd/hostapd.conf

dhcpd のポートが開いている

$ sudo netstat -ap | grep dhcpd
udp     0   0 *:bootps          *:*         651/dhcpd       
udp     0   0 *:20899           *:*         651/dhcpd       
udp6   0   0 [::]:60482        [::]:*       651/dhcpd       
raw     0   0 *:icmp              *:*    7   651/dhcpd       

無線LANのIPアドレスが 192.168.42.1 になっている

$ ifconfig
wlan0     Link encap:Ethernet  HWaddr cc:e1:d5:3e:33:87  
  inet addr:192.168.42.1  Bcast:192.168.42.255  Mask:255.255.255.0
  inet6 addr: fe80::3640:cb77:8e64:6f8a/64 Scope:Link

ルーティングが設定されている

$ sudo iptables -L
...
Chain FORWARD (policy ACCEPT)
target     prot opt source      destination         
ACCEPT   all  --  anywhere    anywhere   state RELATED,ESTABLISHED
ACCEPT   all  --  anywhere    anywhere            
...

参考
How to Set up a Raspberry Pi as a Wireless Access Point
Raspberry Piのアクセスポイント化 & ルータ化がうまくいかない時はこの通りにやればおk
Raspberry Piの無線LANアクセスポイント化


ラズパイ 無線LANの設定


無線LAN は、無線通信を利用してデータの送受信を行うLANシステムのことです。WLAN( Wireless LAN ) とも呼ばれます。
WiFi とも呼ばれますが、これは Wi-Fi Alliance によって認定された無線LANの規格のことです。

設定
ラズパイに無線LANドングルを差す。
SSID と PASSPHRASE を指定して、/etc/wpa_supplicant/wpa_supplicant.conf に追記する

$ sudo sh -c 'wpa_passphrase YOUR_SSID YOUR_PASSPHRASE >> /etc/wpa_supplicant/wpa_supplicant.conf'

設定前

$ cat /etc/wpa_supplicant/wpa_supplicant.conf
country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

設定後

$ cat /etc/wpa_supplicant/wpa_supplicant.conf
country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
# 下記が追加されている
network={
	ssid="YOUR_SSID"
	#psk="YOUR_PASSPHRASE"
	psk=3195a94c445ee8b8160002f5621ca6b195543c75fa95744cef4c87cf6e693dea
}

確認
下記のように wlan が表示されれば、OK

$ sudo /etc/init.d/networking restart
$ ifconfig
...
wlan0     Link encap:Ethernet  HWaddr cc:e1:d5:3e:33:87  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

再起動する

$ sudo reboot

パソコンから ping コマンドを打って、応答が返ってくれば、OK

$ ping raspberrypi.local

参考
SETTING WIFI UP VIA THE COMMAND LINE
raspberry pi2 で 無線 LAN 設定まで


WiFiServiceDiscovery – Android 4.1


20120329wifi_service_discovery_chat

Android 4.1 から Network Service Discovery がサポートされました。
マルチキャスト DNS をベースにした Service Discovery です。
Wifi 上にある Peer デバイスから提示されたサービスを見つけて接続します。
デバイスは、プリンタ、カメラ、メディア・プレイヤー、およびローカル・ネットワーク上で登録されているその他のものです。

サンプルコード

Android 4.2 の SDK の サンプルコードに WiFiServiceDiscovery が入りました。

Android 4.1 の端末が借りられたので、試してみました。
操作した感触では WiFiDirectDemo とさほど変わらないですね。

(1) 起動すると、通信可能なデバイスを検索します。
(2) 相手が見つかると、一覧に表示します。
(3) 相手に接続すると、チャットを開始できます。

20120329wifi_service_discovery_search20120329wifi_service_discovery_list20120329wifi_service_discovery_chat

Network Service Discovery の解説

公式サイトに解説が載っています。
Connecting Devices Wirelessly

(1) Network Service Discovery を使用する
自分のアプリにて、サービスを開始する方法を学習します。
ローカル・ネットワーク上であるサービスを発見します。
あなたが接続したいサービスに関して、詳細情報を得るために Network Service Discovery を使用します。

(2) Wi-Fi Direct で接続する
近くにある Peer デバイスの一覧を取得する方法を学習します、
レガシーデバイスのためにアクセス・ポイントを作ります、
および、Wi‐Fi Direct が可能なデバイスに接続します。

(3) Service Discovery のために Wi-Fi Direct を使用する
同じネットワーク上にないが、Peer デバイスによって公表されたサービスを、Wi-Fi Direct を使って発見する方法を学習します、

サンプルコードの解説

8つのソースがあります。

(1) WiFiServiceDiscoveryActivity.java
メインの Activity です。
起動すると、通信可能なデバイスを検索します。
相手が見つかると、一覧に表示します。
相手に接続すると、チャットを開始します。

(2) WiFiDirectServicesList.java
接続可能なデバイスの一覧を表示する Fragment です

(3) WiFiDirectBroadcastReceiver.java
wifi p2p events を受け取る BroadcastReceiver です。

(4) WiFiP2pService.java
サービスの情報を格納するコンテナです。

(5) GroupOwnerSocketHandler.java
ServerSocket を実行する Thread です。
wifi p2p group owner が使用します。

(6) WiFiChatFragment.java
チャットを表示する Fragment です。
メッセージをリスト形式で表示します。
Send ボタンでメッセージを送信します。

(7) ChatManager.java
チャットを実行する Runnable です。
ソケット・バッファーを介してメッセージのリードとライトを行います。

(8) ClientSocketHandler.java
ChatManager を実行する Thread です。


WiFiDirectDemo – Android 4.0


20120701wifi_direct_list

Android 4.0 から、Wi-Fi Direct API がサポートされました。
Wifi でピアツーピアのネットワーク接続を作ります。

WiFiDirect のサンプルコードが公開されています。

Android 4.0 の端末が借りられたので、試してみました。
(1) 起動すると、アクションバーに検索ボタンが表示されます。
(2) 検索ボタンにタッチすると、接続可能なデバイスを検索します。
(3) 相手が見つかると、一覧に表示します。

20120701wifi_direct_main20120701wifi_direct_searching20120701wifi_direct_list

(4) 一覧の項目にタッチすると、詳細情報が表示されます。
Connect ボタンにタッチして、相手に接続します。
(5) 接続すると、その旨が表示されます。

20120701wifi_direct_select20120701wifi_direct_connected

(6) 相手側に Lanch Gallery ボタンが表示されます。
ボタンにタッチして、ギャラリーを開きます。
(7) ギャラリーから画像を選択します。
相手側に画像が転送されます。

20120701wifi_direct_peer_connected20120701wifi_direct_peer_gallery

(8) 自分に転送された画像が表示されます。

20120701wifi_direct_transfered


サンプルコード WiFiDirectDemo


WiFiDirectDemo – Wi-Fi Direct Demo の日本語訳
これは Wi-Fi Direct API を利用して、ピアツーピアのネットワーク接続を作る方法を示すデモアプリケーションです。
このアプリケーションは、接続完了した後に、ギャラリーからjpeg画像を転送することができます。
このデモアプリケーションのソースコードは、Wi-Fi Direct API を利用して、3つの重要な事柄を達成する方法を示しています。
・接続相手 (peer) を発見する。
・Wi-Fi Direct API を利用して接続する。
・ファイルを転送するためにTCPソケットを開くことができるように、post connection に関するグループの詳細を見つける。

下記のアプリケーションが含まれています。
・WiFiDirectActivity
メインの Activityです。 アプリのUIとピアのライフサイクルを処理する2つのフラグメントが含まれています。 また、Wi-Fi Direct に関連するイベントに対するブロードキャストレシーバを登録します。

・WiFiDirectBroadcastReceiver
BroadcastReceiver です。 Wi-Fi Direct 関連するイベントをリッスンし、WiFiDirectActivity にそれらを渡し、必要なアクションに対する fragments を持つ。

・DeviceListFragment
ListFragment です。 利用可能なピアとそのステータスが表示します。

・DeviceDetailFragment
Fragment です。 選択したデバイスの詳細を表示し、接続、切断、およびデータ転送を駆動します。

・FileTransferService
IntentService です。 TCPソケットを使用して、アプリケーションからファイル転送を実行します。

あなたが Wi-Fi Direct API を使用するアプリケーションを開発している場合、Android 4.0(API 14)以降のバージョンのプラットフォームでのみサポートされていることに注意してください。
アプリケーションが Wi-Fi Direct モードをサポートする機能を持つしているデバイスにのみインストールすることを保証するために、Android マーケットに公開する前に、アプリケーションのマニフェストに次の内容を追加してください。

・<uses-sdk android:minSdkVersion=”14″ />
アプリケーションは Android 4.0 以上が必要である Android マーケットとプラットフォームに示します。
詳細については、API Levels および <uses-sdk> 要素のドキュメントをご覧ください。

Wi-Fi Direct モードをサポートしていない端末に、あなたのアプリケーションをインストールしないように、Android マーケットに通知するのは、アプリケーションのマニフェストに以下を追加してください

・<uses-feature android:name=”android.hardware.wifi.direct” />
あなたのアプリケーションが Wi-Fi Direct API を使用していることを、Androidマーケットに通知します。 Wi-Fi Direct モードをサポートしていない端末に、あなたのアプリケーションをインストールしないように、Android マーケットに通知するのは、宣言に android:required 属性が含まれている必要があります。 他の <uses-feature> 宣言もあなたの実装によっては必要かもしれません。 詳細は、 <uses-feature> 要素のドキュメントを参照してください。

Wi-Fi Direct API の使用方法の詳細については、 android.net.wifi.p2p のドキュメントを参照してください

動作確認
Wifi機能がないエミュレータなので、動作確認はできず。

追記 実機で動作確認しました

ソースコード
5つのファイルがある。

・WiFiDirectActivity
Activity を継承し WifiP2pManager.ChannelListener (API 14) と DeviceListFragment.DeviceActionListener (自作) を実装する。
メインの Activityです。

・WiFiDirectBroadcastReceiver
BroadcastReceiver を継承し WifiP2pDevice (API 14) を使用する。
Wi-Fi Direct 関連するイベントを受取る BroadcastReceiver です。

・DeviceListFragment
ListFragment を継承し WifiP2pManager.PeerListListener (API 14) を実装する
利用可能なピアを表示する ListFragment です。

・DeviceDetailFragment
Fragment を継承し WifiP2pManager.ConnectionInfoListener (API 14) を実装する。
選択したデバイスの詳細を表示するなどの Fragment です。

・FileTransferService
IntentService を継承する。
ファイル転送を実行する IntentService です。

関連記事
サンプルコード ActionBarCompat
サンプルコード AndroidBeamDemo
サンプルコード SampleSpellCheckerService
サンプルコード TtsEngine
サンプルコード VoicemailProviderDemo
・サンプルコード WiFiDirectDemo