D言語で電子錠システムを作っている話

これは[D言語 Advent Calendar 2016](http://qiita.com/advent-calendar/2016/dlang) 16日目の記事です。
#はじめに
この記事では今年の4月あたりから卒業研究として制作している電子錠システムを紹介したいと思います。

先にどのようなものを作ったか、画像と動画を載せておきます。
![システム外観.jpg](https://qiita-image-store.s3.amazonaws.com/0/130197/f526704c-ab9c-6bd8-f627-a297011fe4f7.jpeg)
制御はRaspberry Pi3です。見た目はひどいですがちゃんと動きます。下にArduinoが見えますが過去のシステム(後述)で使っていたもので関係ありません。

[![動作動画](http://img.youtube.com/vi/Nq2wMxQslVU/0.jpg)](http://www.youtube.com/watch?v=Nq2wMxQslVU)
このようにFeliCaタグを読み取り部に近づけると鍵の開閉を行ってくれます。一人で撮ったのでブレてたり全体が写ってなかったりしますが雰囲気はわかるかと思います。

[GitHub - ekeymgr](https://github.com/ray45422/ekeymgr)
GitHubに公開しているリポジトリです。


#なぜD言語なのか
最初はC++かPythonで開発しようと思っていました。C++は少しは書けるのですが、ポインタがよくわからず、ビルドが面倒なイメージがありました。Pythonも少し書いたのですが、まず文法が苦手だったのと実行速度が足りませんでした。そんな時に現れたのがD言語です。
D言語にはDUBというパッケージ管理システムがあり、コンパイル、ライブラリとのリンクも行ってくれます。C言語風の構文で書きやすく初心者の僕でもそれなりのものが書けました。Raspberry Piで動くので今回のシステムを作るにあたって必要な条件を十分満たしていました。なにより「D言語はいいぞ」と複数の人から勧められたされたことが1番大きいです。

#開発の経緯
ここでこのシステムを開発するに至った経緯を軽く説明したいと思います。
僕の通う高専には5年に卒業研究という科目があります。3月ごろ無事進級が決まって担当教員に研究テーマを決めるように言われ何も思いつかず困っていました。
ふと僕は過去にArduinoを使って電子錠システム制作したことを思い出しました。このシステムは教員から、実験室の鍵を電子化するが誰かやらないか、との提案がありソフトウェアを担当した僕を含む6人程度で制作したものです。また同様のシステムが配属された研究室に設置されていました。しかし、そのシステムにはIDを登録すると登録抹消するにはそれなりの手間がかかる、誰がいつ開けたなどの情報を確認できない、登録できるIDの数も少ないといった問題点がありました。
そこで今ある電子錠システムを改良するという案を出すとOKが出たのでこれを開発することになりました。

#システム概要
##環境
- ボード
以下の理由からRaspberry Pi3を選択しました。
  - Raspberry Piシリーズでは1番性能が高いためビルドが早くなるという期待
  - 時間があればスマートフォンアプリ作ってBluetoothで操作したい
  - Wi-Fiが実装されているので取り回しの悪いLANケーブルを使わずにすむ

- OS
Raspberry PiといえばRaspbianがよく使われていますが、今回使ったのは[Arch Linux ARM](https://archlinuxarm.org/)です。
選んだ理由は、Raspbianのコンパイラは古く(ldc v0.14.0)mysql-dをビルドできませんでした([こんなエラーメッセージが出た](https://gist.github.com/ray45422/89d550622e3e8a0c0d2f27770549c256))。ソースコードの修正は手に負えないだろうし、コンパイラをビルドするのが面倒だったからです。ちょうどあったArch Linux ARMの環境ではldc(v0.17.1)でビルドできたのでそちらで開発しているという状態です。

- D言語
コンパイラはldcを使用しました。
まずdmdはARM版が提供されていません。またgdcがダメな理由はmysql-dではpragmaが使われていますが、gdcはこれをサポートしていません。よってコンパイラはldcしか使えなくなりました。
先にも述べましたがパッケージ管理にはDUBを使用しました。
ライブラリのダウンロードからビルドまでやってくれる便利なツールです。これがなかったらおそらくD言語は使ってなかったでしょう。

- データベース
認証情報、ログなどの管理にはMariaDBを使用しました。
MariaDBはMySQL派生のデータベース管理システムです。mysql-dを使い、ローカルORリモートに設置されたDBとやり取りをします。

- ブラウザインターフェース
ログをブラウザから閲覧するためにnginxとPHPでhttpサーバーを建てました。Bootstrapの乱用でそれっぽい見た目にすることに成功ました。

##機能
- 鍵の開閉
最初の写真からわかるように、システムを設置する扉は学校によくあるであろう普通の引き戸です。内側にあるつまみを上下に動かすことで鍵の開閉ができます。RCサーボモータを設置してサーボホーンに取り付けた板で引っ掛けて動かしてやるだけなので仕組みはとても簡単です。ここでは金属板を曲げていますがタミヤのキットなどでも十分でしょう。このRCサーボモータはPWM方式なので、Raspberry PiのGPIOから適当なパルスを出力してやります。D言語でGPIOを操作するライブラリとして[dgpio](https://code.dlang.org/packages/dgpio)があります。これを使ってパルスを出す[ライブラリ](https://github.com/ray45422/ekeymgr/tree/dev/servo)を書きました。ArduinoのServoを劣化コピーした感じですね。
違うタイプの鍵の場合は処理を書き直す必要があるので、少し面倒です。

- FeliCa IDの読み取り
使用したFeliCaリーダライタはソニーの[RC-S620/S](https://www.sony.co.jp/Products/felica/business/products/RC-S620.html)です。過去のシステムで使っていたものをそのまま流用しました。シリアル通信ライブラリは[serial-port](https://code.dlang.org/packages/serial-port)を使用しました。
通信方法が公式のドキュメントで用意されている上にArduino用のライブラリがあるのでこれらを参考にして実装しました。作ったライブラリが[これ](https://github.com/ray45422/ekeymgr/tree/dev/RCS620S)です。今回使うのはFeliCa IDだけなので必要最低限の機能しか実装されていません。
これはD言語使い始めてすぐに実装したのですが、スライスのおかげで楽に移植することができました。
ちなみにRaspberry Pi3ではGPIOのTx,Rxは簡単には使えません。なのでUSB-シリアル変換基板を使用しています。

- 認証
SQL文を作成して`mysql-d`でデータベースサーバに問い合わせます。[コード](https://github.com/ray45422/ekeymgr/blob/dev/source/auth.d)

- ブラウザからの操作
ブラウザからログの閲覧、ユーザー登録、鍵の開閉などを行えるようにします。
![log.jpg](https://qiita-image-store.s3.amazonaws.com/0/130197/164ab787-d343-4594-d838-3ffd5cd28878.jpeg)


- 利用期限、利用時間の設定
利用できる期限を設定したり、授業のある日だけ使えるようにしたいときなどもあるでしょう。

- 複数部屋管理
複数の部屋に設置したとき、同じユーザー情報を何度も登録するのは面倒です。データベースを1つにまとめて管理を簡単にできるようにします。

- ユーザーのグループ化
クラス(学級)単位で利用を許可したいなどのときはグループ化しておくことで、まとめて利用条件を設定することができます。

これくらいができれば改良したと言えるでしょう。

本体はサーバーとして動作させ、TCP/IPソケットでクライアントとの通信を行います。通信には`std.socket`を利用しました。

#コードを書いててハマったところ

- 他スレッドと変数の共有  
メインスレッドで値を書き込んだグローバル変数を他のスレッドから読めなかった。他のスレッドから読むには`shared`をつけないとダメらしい。
- TCPソケットを閉じた後しばらく開き直せない  
デーモンを再起動させようと思ってもなぜかそのポートは使われている例外が発生する。1分くらい待つと起動できるし、終了時にはソケットを閉じているので原因がわからない。

#まとめ
長々と書いておいてD言語 Advent CalendarなのにあんまりD言語の話をしてないような気がします。ごめんなさい。
いつもはTwitterに断片的につぶやいてばかりだったのでまとめるのが大変でした。こういった形で文章を書くのは初めてなので少し大目に見てもらえるとありがたいです。
今回はこんな微妙な記事になってしまいましたが、D言語はいろいろなことができて楽しいです。来年にはもっと文章力を高めてD言語の良さをより伝えられるようになりたいです。最後まで読んでくれてありがとうございます。