[WIP] dronekitコードリーディング

- そもそもdronekitが使いたいわけじゃなくて、pymavlinkを使いたい
- pymavlinkでハートビートを送出して、3DR soloにハートビートを送り返してもらうところまでやりたい
- dronekitの`connect()`を実行するとハートビートが返ってくるが、同じことを素のpymavlinkでやる方法がわからない
- チュートリアルもあるようでない
- `connect()`のコード読んだらいいのでは？

3DR Soloのネットワークに接続して、

```
from dronekit import connect
vehicle = connect('udpin:0.0.0.0:14550', wait_ready=True)
```

とやってからパケットキャプチャしてみると、Macからハートビートを送っているようだし、3DR soloもハートビートを送ってくるようになるので、`connect()`の中に通信開始処理があるに違いない。（この名前で無かったら悲しい）

`connect()`の定義を探してみる。
[__init__.py#L3085](https://github.com/dronekit/dronekit-python/blob/0eb7715bd9392c36e8ab6901a4546ae20c424918/dronekit/__init__.py#L3085)にある模様。

ちょっと飛ばして、[__init__.py#L3166](https://github.com/dronekit/dronekit-python/blob/0eb7715bd9392c36e8ab6901a4546ae20c424918/dronekit/__init__.py#L3166)のif文は、`wait_ready=True`なので、[#L3168](https://github.com/dronekit/dronekit-python/blob/0eb7715bd9392c36e8ab6901a4546ae20c424918/dronekit/__init__.py#L3168)の、

```python
vehicle.wait_ready(
still_waiting_interval=still_waiting_interval,
still_waiting_callback=still_waiting_callback,
timeout=timeout
)
```

が実行される。
`still_waiting_interval`はデフォルト引数の`still_waiting_interval=1`から`1`、`still_waiting_callback`もデフォルト引数の`still_waiting_callback=default_still_waiting_callback`から`default_still_waiting_callback`が与えられている。

`default_still_waiting_callback`の定義は[__init__.py#L3081](https://github.com/dronekit/dronekit-python/blob/0eb7715bd9392c36e8ab6901a4546ae20c424918/dronekit/__init__.py#L3081)にある。
内容はただログを出力しているだけ。

続いて、`vehicle.wait_ready()`の定義を見てみる。見てみたいのだが、`vehicle`がなんなのかぱっと見でわからない。
[__init__.py#L3157](https://github.com/dronekit/dronekit-python/blob/0eb7715bd9392c36e8ab6901a4546ae20c424918/dronekit/__init__.py#L3157)まで戻って、`vehicle`オブジェクトの出処を調べてみる。

```python
handler = MAVConnection(ip, baud=baud, source_system=source_system, use_native=use_native)
```

は、`connect()`を呼び出したときの引数とデフォルト引数から、

```python
handler = MAVConnection('udpin:0.0.0.0:14550', baud=115200, source_system=255, use_native=False)
```

と呼び出されているはずだ。

`MAVConnection()`の定義を見てみる。

[mavlink.py#L124](https://github.com/dronekit/dronekit-python/blob/f786a6323191ab1fe0cf252111262287ff511adb/dronekit/mavlink.py#L124)にある。

`ip`が`'udpin:0.0.0.0:14550'`だから、[mavlink.py#L127](https://github.com/dronekit/dronekit-python/blob/f786a6323191ab1fe0cf252111262287ff511adb/dronekit/mavlink.py#L127)のif文の`ip.startswith("udpin:")`はTrueになる。

[#L128](https://github.com/dronekit/dronekit-python/blob/f786a6323191ab1fe0cf252111262287ff511adb/dronekit/mavlink.py#L128)の

```python
self.master = mavudpin_multi(ip[6:], input=True, baud=baud, source_system=source_system)
```

は、

```python
mavudpin_multi('0.0.0.0:14550', input=True, baud=115200, source_system=255)
```

となるはず。
続いて、`mavudpin_multi()`の呼び出しを追ってみる。

小文字のスネークケースなので関数呼び出しかと思ったらこれはクラスのコンストラクタらしい。
定義は[mavlink.py#L40](https://github.com/dronekit/dronekit-python/blob/f786a6323191ab1fe0cf252111262287ff511adb/dronekit/mavlink.py#L40)にある。

頭のスタックが少ないので渡されてきているはずの引数をメモしておく。

```python
device='0.0.0.0:14550'
baud=115200
input=True
source_system=255
# 以下はデフォルト引数より
broadcast=False
use_native=False  # 定義は https://github.com/ArduPilot/pymavlink/blob/master/mavutil.py#L36 にある
```

[mavlink.py#L52](https://github.com/dronekit/dronekit-python/blob/f786a6323191ab1fe0cf252111262287ff511adb/dronekit/mavlink.py#L52)のif文は`input=True`なのでif節が実行される。

[mavlink.py#L53](https://github.com/dronekit/dronekit-python/blob/f786a6323191ab1fe0cf252111262287ff511adb/dronekit/mavlink.py#L53)の`setsockopt()`の動作を簡単に調べてみる。

```python
self.port.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
```

ソケットに`SO_REUSEADDR`を設定すると、複数のプロセスからbindできるようになる模様。
参考: http://jis.hatenablog.com/entry/2013/09/11/143723

このへんまで読んで、`mavutil.mavlink_connection()`出てきてなくね？あれ？？？
まあいいや、ひととおり読もう。
続く・・・