4
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

Organization

Electronで作った京浜急行運行情報監視ウィジェットを支えるクソコードたち

こんにちは、ポキオ(@pokiiio)です。IoTLT Advent Calendar 2018の12日目を担当させていただきます。

ポキオ 京急 運行情報 ウィジェット

tl;dr

京浜急行の運行情報を監視するアプリをElectronで書きました。Electronなので、macOSでもWindowsでもきっと動くはずです。Node環境(当方はv8)があればすぐに使えますので、ぜひお使いください。

上記リポジトリからソースをClone or Downloadして、

npm install

で必要なファイルをダウンロードし、

npm start

で起動します。また、パッケージ化したい場合は、

npm run build-macOS

で可能です。Windowsユーザーの方は、build-macOSの部分をbuild-windowsに変えて実行してみてください。

この期に及んでなぜElectron?

いままでIoTLTを中心に登壇させていただきましたが、それを同時に京急にまつわるガジェットをたくさん作成してまいりました。ご縁もありMakerFaireTokyo2018でも展示させていただきました。

pokiiio Maker Faire Tokyo 2018

ただ、物理的なガジェットの最大の欠点として、持ち歩くのが面倒という点が挙げられます。

そこで、今回は物理的なガジェットではなく、京急に関するデスクトップアプリを作りました。その実現方法として、いちばん最短ルートっぽかったのがElectronだったので、その紹介もさせてください。

勤務先のデスクには、過去作成したガジェットをいくつかおいてありますが、たとえばミーティングのために別の部屋に移動した際に、ガジェットを持っていくのは面倒です。でも、京急をつねに肌で感じていたい。そこでたどり着いたのがパソコン上で動作するデスクトップアプリでした。

Electronとは

Screen Shot 2018-12-05 at 0.50.03.png

ちょっと雑ですが、HTML+CSS+JSでクロスプラットフォームなデスクトップアプリが書ける仕組み、というふうに理解しています。豊富なnpmモジュールを使えるので便利な一方、BootstrapなどオサレなUIコンポネントも使えるので、ちゃちゃっとデスクトップアプリがかけてしまうのです。

つくったもの

これ。

ポキオ 京急 運行情報 ウィジェット

(表示内容はダミーです)

京急の運行情報を定期的に取得し、遅延などが発生しているときはデスクトップ上部に情報を表示するというものです。普段はアプリを起動しっぱなしにしておくのですが、何も表示されません。

技術的なポイント

以下の3つです。

  • 京急の運行情報取得方法
  • 運行情報だけを表示させる
  • マルチスクリーン対応

京急の運行情報取得方法

これに関しては、今までのガジェット作成のノウハウがふんだんに(?)使われています。基本的には京急の情報ページ( http://unkou.keikyu.co.jp/ )から取得してくるのですが、

<div class=unko-panel>
京急線は平常通り運転しています。
</div>

運行情報はunko-paneldivで囲まれています。したがって、JSでこれをパースするには、よしなにrequest-promiseとかでbody全体を取得した後に、

let info = body;
info = info.split('<div class=unko-panel>')[1];
info = info.split('</div>')[0];
info = info.trim();
return info;

こんな感じでゴリゴリパースすると、簡単に運行情報が取得できます。

運行情報だけを表示させる

通常、Electronアプリを作成して実行すると、Windowとして表示されてしまうので(あたりまえですが)、Windowを透明にしたり、メニューバーなども非表示にしてあげることで、あたかも運行情報だけが表示されてるかのように表現することができます。

具体的には、BrowserWindowをnewするときに、オプションで以下のパラメータを与えてあげます。

width: size.width,
height: size.height,
// where size is display size.
frame: false,
transparent: true,
resizable: false,
alwaysOnTop: true,
  • widthheightには表示しようとしているディスプレイのサイズを与えて、全画面表示をする
  • framefalseにしてウィンドウのタイトルバーを非表示する
  • transparenttrueにして、Windowを透明にする
  • resizablefalseにして、常に全画面表示とする
  • alwaysOnToptrueにして、常に最前面に表示されるようする

ただし、最後のalwaysOnToptrueにしてしまうと、クリックイベントをすべてこのElectronアプリが奪ってしまうことになるので、下記のようにクリックイベントを下のレイヤーにスルーパスして上げる必要があります。

window.setIgnoreMouseEvents(true);

マルチスクリーン対応

仕事では、外部ディスプレイに接続してマルチスクリーンで仕事をすることも多いと思います。アプリでも、スクリーン数の変化を検知して、すべての画面に運行情報を表示できるようにしています。

electron.screen.on('display-added', function () {
  ...
});

electron.screen.on('display-removed', function () {
  ...
});

こんな感じでelectron.screenがEmitするイベントを受けるだけ。これをうけて、electron.screen.getAllDisplays()とかすると、接続中の画面がすべて取得できるので、それぞれの画面に対してBrowserWindowをnewして表示さればOK。

ただし「このDisplayに、このBrowserWindowを表示する!」みたいな便利なオプションはないので、画面の絶対座標を指定して、BrowserWindowをnewして上げる必要があります。

let window = new BrowserWindow({
  x: display.bounds.x,
  y: display.bounds.y,
  ...
});

サマリ

今回は、Electronでアプリを作ってみました。簡単にデスクトップアプリが作成できるので、みなさんもオレオレアプリを作ってはいかがでしょうか?

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
4
Help us understand the problem. What are the problem?