MacBook Proの充電器の情報をメニューバーに表示するElectronアプリをつくった

MacBook Proで使われてるType-Cの充電は条件により充電速度が変わってきます。

例えば、私の場合RAVPowerのType-AとType-Cの両方が使え 最大60W まで供給できる充電器を普段使いしています。

[<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7132/c33e91d2-5944-ea77-8b5f-ee6f67e0e3cb.png" width="300">
](https://amzn.to/2sWzGPz)

しかしType-AとType-CにそれぞれiPhoneとMacBook Proへ同時に充電しようとすると、45W に供給される電力が低下してしまいます。

この状態で頑張って仕事していると、徐々バッテリーが減っていってしまいます。
減らないにしても充電速度がかなり遅くなる。


<br>
充電器、ケーブル、PD対応など、Type-C関連は仕様が複雑過ぎるので、繋いでみないと正直わかりません。
充電できたとしても、この供給電力の情報はかなり奥まったところにあるので確認しづらい。
ならメニューバーに表示するアプリをつくってしまえ！


## つくった
`Charger Information for Mac` というアプリをElectronでつくりました。

https://github.com/narikei/Charger-Information-for-Mac
[<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7132/9eb4aa36-ab12-a72d-7022-26ebb4e25e2c.png" width="300">
](https://github.com/narikei/Charger-Information-for-Mac)

アプリを導入すると画面上部のメニューバーに充電器の供給電力が表示されます。
[<img width="468" alt="スクリーンショット 2019-12-08 16.29.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7132/633a4306-175c-079d-bcc3-1471c42da92a.png">
](https://github.com/narikei/Charger-Information-for-Mac)


[<img width="319" alt="スクリーンショット 2019-12-08 16.28.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7132/eaa91d02-46c6-4ec8-700d-49e784b59d31.png">
](https://github.com/narikei/Charger-Information-for-Mac)


# さらにつくった
このアプリをちゃんとSwiftで作り直しました。
Electronから乗り換えたことでマシンリソース消費を削減し、
こっちはMac App Storeで配信もしてみました。（１月中は無料で公開しています！）
[https://apps.apple.com/jp/app/wattageviewer/id1548099536?mt=12](https://apps.apple.com/jp/app/wattageviewer/id1548099536?mt=12)
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7132/2d2d47e9-260b-24a5-e856-d54c572d8d77.png)](https://apps.apple.com/jp/app/wattageviewer/id1548099536?mt=12)


## 充電情報の取得
Macの場合この詳しい充電器の供給電力の情報はシステムレポートから確認しないといけないのですが、
`ioreg` コマンドで取得することができます。

```
$ ioreg -rn AppleSmartBattery | grep '"AdapterDetails"'
      "AdapterDetails" = {"Watts"=30,"Current"=1500,"PMUConfiguration"=0,"Voltage"=20000}
```


**Watts**: 電力（W）
**Current**: 電流（mA）
**Voltage**: 電圧（mV）
とそれぞれ取得できます。
電流と電圧は1/1000で計算すると単位からmがとれてわかりやすい。


### Node.jsからMacのコマンドを叩く
`child_process` でOSのコマンドを実行することができます。
`execSync` は同期。

```js
const { execSync } = require('child_process');
const stdout = execSync('ioreg -rn AppleSmartBattery | grep \\\"AdapterDetails\\\"');
```


## メニューバーへアイコンの表示
`Tray` というモジュールを使いメニューバーにアイコンを追加できます。

```js
const { app, Tray, Menu, MenuItem } = require('electron');
const ICON_PATH = 'icon.png';
app.on('ready', () => {
  const appIcon = new Tray(ICON_PATH);
  const menu = new Menu();

  menu.append(new MenuItem({
    label: 'item',
    click: () => {
      alert('click item');
    },
  }));
  menu.append(new MenuItem({ type: 'separator' }));
  menu.append(new MenuItem({ role: 'quit' }));

  appIcon.setContextMenu(menu);
});
```

<br>
こんな感じの記述で充電状態と非充電状態でアイコンを変えられます。

```js
  if (!isCharging()) {
    appIcon.setImage(ICON_MISSED_PATH);
    return;
  }

  appIcon.setImage(ICON_CHARGING_PATH);
```


## Dockからアイコンを非表示にする
Electronアプリを実行すると、Dockにアイコンが表示されますが、
こういった常駐型のアプリではDockにあっても邪魔なだけなので非表示にします。
`app.dock.hide()` で非表示になる。

```js
const { app } = require('electron');
app.on('ready', () => {
  app.dock.hide();
});
```



## 充電情報を通知する
`Notification` モジュールを使いMacの通知機能に投げることができます。
充電情報が変化したときに、通知できるようにしました。

<img width="382" alt="スクリーンショット 2019-12-08 16.28.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7132/cc1016fe-2771-6967-2070-5a6c24e8cf8b.png">

```js
const { app, Notification } = require('electron');
app.on('ready', () => {
  const notification = new Notification({
    title: '⚡Charging',
    body: 'Power: 30W\nVoltage: 20V / Current: 1.5A',
    silent: true,
  });
  notification.show();
});
```

`\n`で改行できますが、どうも最初の１つ以降は無視されるっぽい。。。


## ダークモード対応する
ダークモードなる存在を完全に忘れていた。（[https://github.com/narikei/Charger-Information-for-Mac/issues/2](https://github.com/narikei/Charger-Information-for-Mac/issues/2)）


```js
const { app, nativeTheme } = require('electron');
app.on('ready', () => {
  if (nativeTheme.shouldUseDarkColors) {
    charging_path = ICON__WHITE_PATH;
    return;
  }

  appIcon.setImage(ICON__BLACK_PATH);
});
```


## アプリケーション化する
Electronのビルドにはいくつかやり方があるのですが、
個人的には `electron-builder` でパッケージングするのが簡単


### 追加
`devDependencies` にしないとビルド時に怒られます。

```
$ yarn add --dev electron-builder
```


### アイコンの作成
`icons.iconset` というディレクトリーを作り、その中に各サイズのアイコン画像を入れ、
`electron-builder` に渡してあげるだけで良い。

<img width="224" alt="スクリーンショット 2019-12-08 18.11.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7132/3e5c7fcd-10ab-8f91-3965-5dbb819f9773.png">

（今回Dockに表示されないし、導入時にしか見る機会はないが一応、、、）


### ビルド情報を記述
ビルド情報は `package.json` に記述していきます。

```json:package.json
{
  "name": "charger-information-for-mac",
  "main": "main.js",
  "scripts": {
    "build": "electron-builder"
  },
  "devDependencies": {
    "electron": "^7.1.2",
    "electron-builder": "^21.2.0"
  },
  "build": {
    "appId": "com.ozonicsky.charger-information-for-mac",
    "productName": "Charger Information",
    "icon": "icons.iconset",
    "mac": {
      "target": "dmg"
    }
  }
}
```


### ビルドする

```
$ yarn build
```


## おわり

コードはすべてこちらに公開しております。
https://github.com/narikei/Charger-Information-for-Mac

製品版はこちら
[https://apps.apple.com/jp/app/wattageviewer/id1548099536?mt=12](https://apps.apple.com/jp/app/wattageviewer/id1548099536?mt=12)