Speee DEVELOPER BLOG

Speee開発陣による技術情報発信ブログです。 メディア開発・運用、スマートフォンアプリ開発、Webマーケティング、アドテクなどで培った技術ノウハウを発信していきます!

勤怠打刻機をRaspberry Pi 14台で本気で作ってみた

こんにちは、プロジェクト推進室でエンジニアをやっている 山本 (id:bino98) です。

毎日のお勤め、お疲れ様でございます。皆さまが、日々の業務を行われる合間に

  • 有給休暇を取得したり
  • 遅刻の連絡をしたり
  • 出張の申請を行ったり…。

様々な場面で自身の勤怠をその組織のやり方で管理されていると思います。弊社では、今年4月初頭から 社内で開発した新しい勤怠管理システム「 SpeeePORT 」による勤怠管理が始まりました。

弊社の新しい勤怠管理システム(以下、PORT)に関する詳しい記事は、ITproさまがこちらの記事にまとめてくださいましたので、ご覧頂けますと幸いです。

今回、PORTの ウリ の1つの 打刻機 について、まとめました。Raspberry Pi で打刻機を作りたいという、結構ニッチな要求を持つ方のお役にたてれればと思います。

Raspberry Piで打刻機を内製した経緯

こちらの記事にあるように、打刻忘れの問題は以前から発生していました。PORTを利用前の勤怠管理システムでは、出勤・退勤打刻をWebブラウザ上で行う必要がありましたが、その存在は忘れられがちだったのです。

打刻が忘れられないように、ICカードによる打刻の実現が社内で強く求められ、 アップデートされてきた弊社の新しい勤怠制度に適合できる勤怠管理システムを内製で開発することとなりました。

Raspberry Piを利用した理由は、

  • 安価で入手容易である
  • 自分たちの用途に応じてカスタマイズできる
  • PasoriとRaspberry Piを連携された事例がインターネット上に存在する

などの理由で使用することを決めました。

打刻機の利用方法

まず、打刻機の種類の話からですが、PORTでは2種類の打刻機を用意しています。1つは、打刻機。 f:id:bino98ty:20170605101952j:plain

もう一つは、打刻登録機です。 f:id:bino98ty:20170605102119j:plain

打刻機を利用して、勤怠打刻を行うためにはユーザには下記のフローを実施してもらいます。

  1. 個人や会社で利用している 交通系ICカードを用意 してもらう
  2. 打刻登録機 にICカードをタッチしてもらう
  3. 画面にQRコードが表示されるため、手持ちのスマホ等で読み取ってもらう
  4. 読み取ると、カードの登録がされる*1ため、あとは 打刻し放題 になる

打刻登録機はカード登録時に必要ですが、頻度はきっと多くないはず。普段使いの打刻にはディスプレイもキーボードも不要ですね。故に、普段は極力小型で、低コストで量産できるRaspberry Piを用いた打刻機を利用してもらっています。

ピッとすると打刻される仕組み

f:id:bino98ty:20170605110135p:plain

打刻機と打刻登録機は実は使用しているアプリケーションは同じです。まず、Pasori*2を利用するためのライブラリnfcpyをPythonを利用した読み取りプログラムを記述し、そのプログラム上でPORTのAPIに打刻リクエストを送信します。カードが未登録の場合はその旨のレスポンスが返ってくるため、打刻機側でそれを解釈し、同一リクエスト内に含まれるワンタイムURLをQRコードにして、イメージファイルとして保存しておきます。打刻機の場合は、ここまでです。

打刻登録機の場合は、発行されたQRコードを表示するためのプログラムも起動しており、node + expressで動かしてます。nodeでは、QRコードが保存されるディレクトリを常に監視し続け、ファイルに変更があれば(すなわち、QRコードが新たに発行された場合)画面を再描画するような仕組みになっています。

十数台の打刻機があるとたまにサボるやつが居るものだ

Raspberry Piを用いた打刻機ですが、不意に停止してしまうことがあります。例えば、

  • WiFiとのコネクションが切れたまま、復旧せず打刻できなかったり。
  • 一定以上使われないと勝手にプロセスが閉じて打刻できなくなったり。

打刻をするタイミングは朝出社前がほとんどであり、その時間帯に「 打刻機動かんけど、どうなってるの? 」などとお問い合わせを受けると、なかなか辛くてお腹が痛くなると思います。

そこで、PORTの打刻機には監視プログラム、自己診断送信プログラム、再起動プログラムの3つの仕組みを作って対応しています。

監視アプリケーション

監視プログラムでは、読み取りプログラムと表示プログラム、自己診断送信プログラムの3つのプロセスが生きているかを監視し、生きていなかった場合再起動させます。これによって、例えばプログラムに不調が出ても、「Pasoriを一度取り外してもう一度打刻機に接続したらプログラムが正常に動く*3」状態を実現でき、万が一朝に問題が合っても利用者自身で打刻機のプログラムを再起動できるようになっています。

自己診断送信プログラム

自己診断送信プログラムでは、プロセスの状態やインナーIP、GitHubのリビジョンなどを定期的にAPIに送信し続けます。PORTには打刻機監視画面があります。その画面に、このプログラムから送信されてきたデータを基に打刻機が稼働しているか、異常が発生しているかの診断を行い、画面に表示させています。

f:id:bino98ty:20170605112625p:plain

万が一、打刻機が停止している場合は、Slackにその旨のアラートを飛ばし、山本が飛んで直しに行きます。

再起動プログラム

再起動プログラムでは、1時間に1度、読み取りプログラム、自己診断送信プログラム、表示用プログラムの3つを終了します。長時間プロセスを起動し続けると、時たまゾンビプロセス化するプログラムがあるため、定期的に終了しています。しかし、上記の監視プログラムがプロセスを監視しているため、自動で再起動します。

ユーザにどうやって打刻成否を伝えるか

打刻機にはディスプレイがないが、どのように打刻の成否を伝えるか。肝は です。スピーカーはディスプレイよりはるかに安価に調達できますし、打刻機から返されるレスポンスは、ディスプレイほどの情報伝達力を必要としない量のため採用しました。

スピーカーは、100均のモノラルスピーカーを利用するか、 アンプ内蔵のお手製スピーカー を利用します。100均で売られているスピーカーを使うと、Raspberry Piから音を最大音量で出力ししても、ちょっと音が小さいのです。そのため、アンプ内蔵のスピーカーを打刻機を設置する場所によっては採用しています。

アンプ内蔵のスピーカー

安価なアンプ内蔵のスピーカーは、その当時調べた限り、見つけることができませんでした。なので、こちらのパワーアンプキットと、こちらのスピーカーを調達し、自前ではんだ付けし、使っています。現実的な音量になるため、全ての打刻機をこのタイプにしたいのですが、できればはんだ付けしたパーツは使いたくないところ…(打刻機運用の引き継ぎのハードルが途端に上がる)。アンプ内蔵のスピーカーを探しているところです。

f:id:bino98ty:20170605114147j:plain f:id:bino98ty:20170605102237j:plain

音のユーザ体験

また、打刻音にもこだわりが。

当初、打刻音は 打刻成功時に一度「ピッ」となるだけ でした。しかし、打刻成功時だけではレスポンスが帰ってくるまでの1〜2秒を長く体感される方が社内には多く(と思うと、鉄道の改札機ってマジリスペクトするぐらい早く ピッ となってくれますよね)、API側でリクエストの負荷のかかる部分をメッセージキューイングさせ、応答時間そのものを早くしたり、プレ打刻音をならしたりして、ちょっとずつユーザ体験の質の向上を実施してたりします。社内で作っていると、すぐにユーザの反応を受け取れるので、やりやすいです。

無機質な電子工作感を脱したい

また、Raspberry Piをそのまま執務室エリアに置いておくと、いかにも電子パーツ感があるため、インテリアしづらいと思います。その電子工作感をなくすため、また100均でケースを買い込み、スプレーニスと電動ドリルで箱を作ってケースを作ったりしました。

f:id:bino98ty:20170605115817j:plain

チーム内でダサいという意見が頻出したため、このケースは採用されませんでした。 レゴでケースを作ったり、3DCADでモデリングしてたりしますが、まだどうするかは未定です。(Raspberry Piを包み込む人形を作るのはどうかという話もあります)

まとめ

内製で勤怠システムを作ったり、打刻機を制作することで、より弊社のニーズに合うプロダクトを作ることができ、ユーザが近いのですぐにその反応も伺えます。もっと簡単に勤怠管理できる日を目指して、引き続き改良を進めていきます。ご覧いただきありがとうございました。

*1:QRコードはカード登録用のワンタイムURLを発行しています。読み取ると、PORTにログインしているユーザのカードとして登録される仕組み

*2:PORTで利用しているICカードリーダー

*3:Pasoriを外すと例外を吐きプログラムが終了するようになっているため