SORACOM使ってStay at Home! 〜機器の電源をON/OFFしよう

# はじめに

在宅ワークをしていると会社に置いてきた機器はリモートコントロールで動作させることになることが多いと思います。僕の場合はIoTサービスの開発をしていて、家では主にクラウドやWebアプリの開発をすることになるのですが、デバイスからのデータが届かなくなったり、通信が途切れちゃったり、といった不調が発生することがあります。まあ開発中のデバイスなのでそういうこともあるでしょう。

そういうときにちょちょっと機器の電源のON/OFFだけできないかな〜、と思うことはないでしょうか？経験上、電源再投入すればだいたい復帰します。そういうの欲しい。ということで前回に引き続き、[SORACOM Inventory](https://soracom.jp/services/inventory/)と[Wio LTE](https://soracom.jp/products/module/wio_lte/)と[easi](https://github.com/1stship/easi)を使って、「外部から機器の電源をON/OFFできるデバイス」を作ってみましたのでご紹介します。

# 実現方法

電源ON/OFFするためには、電源線を切ったりつないだり、ということが必要です。そのような用途ではリレーを使うと良いでしょう。Grove端子でつながるリレーあるかな、と調べたところ、リレーセレクションページがありました。

https://wiki.seeedstudio.com/Seeed_Relay_Page/

色々ありますね。この中で一番上のものは3.3V系でも使えるみたいです。

https://www.seeedstudio.com/Grove-Relay.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542185/05275506-ee51-f29c-1195-08e8cfa6ecee.png)

定格は5A@250VAC、5A@30VDCとのことなので、まず十分でしょう。リレー本体には10Aって書いてるんだけど余裕を持たせてるのかな？電流が100mAと結構大きめなのはメカリレーなので仕方ないですね。マイコンボードから供給できるかちょっと心配ですが。まあまあお安いので購入してみると、リレーは結構大きく、この定格も納得です。電源線を途中で切って、リレーの端子につなげば、電源ON/OFFをリレーで制御できます。[以前消費電力の実験で使った](https://qiita.com/1stship/items/c8c6283940c1505ec918#wio-lte%E3%81%AE%E6%B6%88%E8%B2%BB%E9%9B%BB%E5%8A%9B%E6%B8%AC%E5%AE%9A)途中で切ったUSBケーブルがあるので、それを使います。（電源線を切ったりつなげたりするので、USBの直流5VをACアダプタ経由で使うくらいならさほど危なくないですが、電圧の高い交流を使う際は、感電や発火にくれぐれもご注意ください）

デバイスへのコマンド送信は、前回と同じくSORACOM Inventoryおよび簡単マイコン遠隔操作プログラム「[easi](https://github.com/1stship/easi)」を使いましょう。僕はこれをマイコンでの遠隔操作の定番プログラムとしたい。

まず電源のON/OFFに使えそうなLwM2Mのオブジェクトを探します。

https://www.openmobilealliance.org/wp/omna/lwm2m/lwm2mregistry.html

を見ると、オブジェクトID:3312に「Power Control」というオブジェクトがあります。しかし用途にあったオブジェクト結構見つかるな。。

https://www.openmobilealliance.org/tech/profiles/lwm2m/3312.xml

このオブジェクトの中を見ると、リソースID:5850に「On/Off」というWriteオペレーションがあります。これを使ってON/OFFすればいいですね。

SORACOM Inventoryはユーザーコンソールで使っても良いのですが、SORACOMのWeb APIやCLIから呼び出すことができます。前回は定時に呼び出したかったのでCloudWatch EventsとLambdaを使いましたが、今回はボタンを使ってみましょう。ボタンを押すとSORACOM Funkを通してAWS Lambdaを起動することができ、LambdaからAPIを呼び出すとSORACOM Inventoryを通してリレーON/OFFコマンドを呼び出せます。

構成としてはこうなります。デバイスを下、クラウドを上に書いてみました。

![relay.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542185/bd199323-fc20-7e6a-0ba7-2127e1dcf8ea.png)

では実装してみましょう！

# 実装

前回と同じく、マイコンの方はeasiを[ダウンロード](https://github.com/1stship/easi/releases)して、ちょっと修正して使います。オブジェクトID:3312、インスタンスID:0のオブジェクトを追加し、オブジェクトID:3312、インスタンスID:0、リソースID:5850に対してtrueがWriteされたらD38ピンがHIGH、falseがWriteされたらD38ピンがLOWになるようにハンドラをセットすれば良いので、こんな感じですね。

```c
#include "easi.h"
#include <WioLTEforArduino.h>

Lwm2m lwm2m;
WioLTE wio;

void setup() {
  delay(200);
  wio.Init();
  wio.PowerSupplyLTE(true);
  logText("POWER ON LTE");
  delay(500);
  if (!wio.TurnOnOrReset()) {
    logText("Turn on error");
    return;
  }

  if (!wio.Activate("soracom.io", "sora", "sora")) {
    logText("Connect error");
    return;
  }
  
  delay(1000);
  lwm2mInit(&lwm2m, "wiolte");
  udpInit(&lwm2m.bootstrapUdp, "bootstrap.soracom.io", 5683);

  pinMode(WIOLTE_D38, OUTPUT);
  digitalWrite(WIOLTE_D38, HIGH);
  addInstance(3312, 0);
  setWriteResourceOperation(3312, 0, 5850, &relay);

  while (!lwm2mBootstrap(&lwm2m)){ }
}

void loop() {
  if (!lwm2mCheckEvent(&lwm2m)){
    delay(100);
  }
}

void relay(Lwm2mTLV *tlv){
  if (tlv->intValue){
    digitalWrite(WIOLTE_D38, HIGH);
  } else {
    digitalWrite(WIOLTE_D38, LOW);
  }
}
```

やはり簡単ですね。Wio LTEをDFUモードにして書き込み、D38にリレーをつなげて、Wio LTEに電源を入れておきましょう。

次はLambdaのコードです。Rubyで書くとこんな感じです。

```ruby
require 'json'
require 'net/http'
require 'uri'

def lambda_handler(event:, context:)
  auth = get_auth
  write_relay(auth, event['clickTypeName'] == "SINGLE")
  { statusCode: 200, body: JSON.generate('Power') }
end

def get_auth
  uri = URI.parse("https://api.soracom.io/v1/auth")
  request = Net::HTTP::Post.new(uri)
  request.content_type = "application/json"
  request["Accept"] = "application/json"
  request.body = JSON.generate({
    "authKey" => ENV["AUTH_KEY"],
    "authKeyId" => ENV["AUTH_KEY_ID"]
  })
  req_options = { use_ssl: true }
  response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
    http.request(request)
  end
  
  JSON.parse(response.body)
end

def write_relay(auth, onoff)
  uri = URI.parse("https://api.soracom.io/v1/devices/#{ENV["DEVICE_ID"]}/3312/0/5850")
  request = Net::HTTP::Put.new(uri)
  request.content_type = "application/json"
  request["Accept"] = "application/json"
  request["X-Soracom-Api-Key"] = auth["apiKey"]
  request["X-Soracom-Token"] = auth["token"]
  request.body = JSON.generate({
    "value": onoff
  })
  req_options = { use_ssl: true }
  response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
    http.request(request)
  end
end
```

今回はボタンでこのLambdaを呼び出します。クリックの仕方によりevent引数に入るclickTypeNameが変わるようになっており、SINGLE、DOUBLE、LONGがあります。SINGLEで電源ON、その他では電源OFFにします。

ボタンとFunk、Lambdaの連携のさせ方は、「SORACOM LTE-M Button デザインパターン」の「ボタンと AWS Lambda 連携をすばやく構築したい ― SORACOM Funk + AWS Lambda パターン」という素晴らしい公式資料がありますので、これを読めばバッチリです。

https://dev.soracom.io/jp/design_patterns/soracom_aws/#aws1

これでボタンを長押し(もしくはダブルクリック)したら電源オフ、シングルクリックしたら電源ONになるシステムが整いました。早速ボタン押してみましょう！

# 実行

手近な機器として、WiFiルーターの電源をOn/Offしてみました。

最初はこの状態です。リレーがつながっていて(赤いLEDが光っている)、WiFiルータの電源も入っています。
![IMG_20200530_015132.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542185/b68d6273-a766-e87c-924a-ebdb215ad862.jpeg)

ボタンを長押しすると電源が落ちました。リレーが切れ(赤いLEDが光っていない)、電源が切れたためWiFiルータも動作していないですね。
![IMG_20200530_015152.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542185/100639b6-f6a9-dfb8-4ce6-0e561d800c83.jpeg)

今度はボタンをシングルクリックすると、再度リレーがつながり、WiFiルータの電源も入りました。成功です！
![IMG_20200530_015215.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542185/9d2641d9-9de9-20bd-e4ad-fc7bb5205bb5.jpeg)

通して動画で見るとこんな感じです。
https://twitter.com/1st_ship/status/1266399457014247425

# おわりに

在宅ワークのみならずIoTの課題の一つとして、現地のデバイスがなんか調子悪くなった時の対処、というのがあります。曖昧な言い方をしているのは、本当に何かよく分かんない謎の様々な要因によって動作しなくなってしまうからです。僕の能力不足も多分にあるのですが、常時稼働タイプのIoTサービスを運用している人なら分かってくれるはず。そういう時、ハード的に電源オンオフできるようになっている、というのは最後の切り札として心強くないですか？（easiの安定性はどうなの？という突っ込みは当然ありますが）

そういえば以前のブログで[電源がオフになったらボタンが起動する](https://qiita.com/1stship/items/6c5df7ddaa98d36984ee)っていうのをやりましたね。組み合わせると、動作系の電源が落ちたら自動的に待機系の電源が立ち上がるシステム、とかもできそう。ちょっと面白い。

マイコンを遠隔操作できるようになると色々やれることも増えますので、ぜひ[Wio LTE](https://soracom.jp/products/module/wio_lte/)と[easi](https://github.com/1stship/easi)を試してみていただければと思います！