RedMobileで位置情報トラッカーを作り、それをバックグラウンドで動かす

# はじめに
こちらは[Node-RED Calendar 2023](https://qiita.com/advent-calendar/2023/node-red) 17日目の記事です。

https://qiita.com/advent-calendar/2023/node-red

Node-REDのアドベントカレンダーは初投稿となります。
稚拙な内容ではございますが、よろしくお願いいたします。
また[後述](#お詫び)しますが、今回の件は<b>かなり限定的な条件でしか使えない</b>内容となっていますが、ご容赦ください。

# 経緯
先日、[web3 Global Hackathon](https://app.akindo.io/hackathons/aA8Ek0mDGS8kdZoMe)というハッカソンへの参加の機会をいただきました。
そこで、自動車の走行経路を保存するための位置情報記録を、Androidスマホで動くNode-RED、[RedMobile](https://play.google.com/store/apps/details?id=com.okhiroyuki.redmobile&hl=ja)で実装しました。

残念ながら1次審査通過できませんでしたが、ハッカソンにエントリーしたプロジェクトは以下となります。

https://app.akindo.io/communities/27mmW8jKji236A0l/products/o677vWdgqUAAdLXK

以前、RedMobileで自動車の走行経路を保存するものについて、以下の記事を書きました。

https://fugiters.net/blog/index.php/2021/12/23/bus_tracker2/

今回は他システムと連携させるため、バックグラウンドで動くよう改良したプロトタイプとなります。
具体的には別のメンバーが作成したWebサービスのフロントアプリ（ブラウザ）からAPIで操作させる形となっています。

# お詫び
今回、張り切って応募したのですが、<b>今回の方法は最近の新しいAndroidのバージョンでは使えないようです。</b>
理由は数年前からバッテリーの消費やプライバシー保護の観点から、<font color="red">バックグラウンドで位置情報を取得することが制限されているため</font>とのこと[【参考文献】](https://blog.ch3cooh.jp/entry/android/get_location_information_in_background)
誠に申し訳ございません・・

ただせっかくなので、条件付きとはなりますが、紹介させてください。
部分的にでも参考になることがあれば幸いです。

今回、私が使用したAndroidスマホは2018年発売の京セラ[Qua phone QZ](https://www.kyocera.co.jp/prdct/telecom/consumer/lineup/kyv44/)（Android 9）となります。

# 事前知識
[前述の記事](https://fugiters.net/blog/index.php/2021/12/23/bus_tracker2/)の通り、RedMobileとSORACOMのサービス（[SORACOM Air for セルラー](https://soracom.jp/services/air/cellular/)、[SORACOM Harvest Data](https://soracom.jp/services/harvest/)、[SORACOM Lagoon](https://soracom.jp/services/harvest/)）を使うと簡単に自動車の走行経路が記録できます。

今回はこれに記録の開始、終了を指示する機能の追加と、これをバックグラウンドで動かす方法をご紹介しようと思います。

今回の構成図は以下となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/31c68f8e-7450-78c3-4508-d54e6d1d1e3e.png)

手持ちの機器だけで構築したので、無駄にモバイルルーターを経由していますが、SIMフリースマホであれば直接SIMを挿してもいいですし、[SORACOM Arc](https://soracom.jp/services/arc/)を使ってもよいです。

また、今回はフロントエンドプログラムから操作できるようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/68670e47-5dc4-a434-50a1-adb0a17fca58.png)

# 手順
ざっくり以下となります。
- [モバイルルーターの作業](#モバイルルーターの作業)
- [スマホの作業１](#スマホの作業１)
    - [RedMobileインストールと初期設定](#redmobileインストールと初期設定)
    - [位置情報の取得とアップロード](#位置情報の取得とアップロード)
- [SORACOMの作業](#soracomの作業)
- [スマホの作業２](#スマホの作業２)
    - [送信オン／オフ機能追加](#送信オンオフ機能追加)
    - [APIを使った送信オン／オフ](#apiを使った送信オンオフ)
- [動作確認](#動作確認)

なお、事前にSORACOMのアカウント作成やSIM購入などが必要となりますが、今回は割愛させていただきます。

# モバイルルーターの作業
以下の手順でモバイルルーターを設定します。

https://qiita.com/ozk009/items/c745325839a41107a7b6

SIMフリースマホにSORACOM SIMを挿入して使う場合は[こちら](https://blog.soracom.com/ja-jp/2019/06/17/try-soracomair/)、SORACOM Arcを使う場合は[こちら](https://zenn.dev/showm001/articles/2021-08-12-01#soracom-arc%E3%81%A7%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B)を参考にしてみてください。

# スマホの作業１
ここでの作業はモバイルルーターではなく、ご自宅などのWi-Fi環境での実施をお勧めします。
## RedMobileインストールと初期設定
Play StoreからRedMobileをインストールします。
インストール後、アプリを起動し、以下の作業を行います。
1. 「keepAwake」をチェックし、「Setting」をタップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/7782ab0e-63fc-dd25-49fc-2034b9e80e7d.png)

1. 位置情報への利用許可のため、「Location」にチェックを入れて、「←」で戻ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/a1b89e49-500b-318a-c409-41da844fd9aa.png)

1. 「Start」をタップし、URLが表示されたら起動完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/2efbe76a-e03d-6a38-6bd5-69d8dca24a40.png)

1. スマホと同じWi-Fi環境に接続したパソコンのブラウザからスマホに表示されたURLにアクセスするとNode-REDの編集画面が表示されます。

## 位置情報の取得とアップロード
1. injectノード、subscribeノード、locationノード、debugノードを下図のように接続し、デプロイします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/b15a2fcd-ca1b-389d-4494-fe70b9aa726f.png)

1. injectノードのボタンをクリックすると、デバッグ画面に緯度経度情報が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/528d75da-1bed-2db4-6456-8d73afe96b23.png)

1. 続いて下図の通り、injectノード、changeノードとhttp requestノードを追加し、それぞれのノードを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/af238c24-0115-568d-5063-9f48630c3dfd.png)

    - 初期化のinjectノードは起動時に実行するため、「Node-RED起動の…」をチェックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/1ce6b486-6941-4f27-6b90-522b4afdbdb2.png)

    - 緯度、経度保存のchangeノードはflow変数にpayloadのlatitude、longitudeを代入するようにします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/d6a6dfd0-3200-f7d6-0840-eb34e85d1fdc.png)
    - 定期送信のinjectノードは「指定した時間間隔」で任意の時間（今回の記事では10秒）ごとに実行されるようにします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/af9980f5-653d-2d48-3343-e1f084f92a92.png)
    
    - 送信データを作成するfunctionノードはflow変数の緯度経度をJSONに変換します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/a13b474b-1e78-bd81-670d-5afbc1276e7d.png)
        ```js
        var data = {};
        data["lat"] = flow.get("lat");
        data["lon"] = flow.get("lon");
        
        msg.payload = data;
        
        return msg;
        ```
    - http requestノードでSORACOMの[Unified Endpoint](https://users.soracom.io/ja-jp/docs/unified-endpoint/)のURL、「http://uni.soracom.io」 にPOSTメソッドで送るようにします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/f7b68a69-805d-2604-3e49-062ae4514754.png)

    設定後、デプロイして、次の設定に移ります。
    
# SORACOMの作業
スマートフォンをSORACOM SIMを挿入したモバイルルーターに接続します。
続けて以下の手順で[Harvest Data](https://soracom.jp/services/harvest/)に保存する設定にします。

https://users.soracom.io/ja-jp/docs/harvest/send-data/

Harvest Dataに保存したデータは[SORACOM Lagoon](https://soracom.jp/services/lagoon/)を使うとより見やすくなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/5c552cef-b465-fd28-1b4d-5711585e88d2.png)

# スマホの作業２
## 送信オン／オフ機能追加
まずは送信のオンとオフをスイッチで切り替えられるようにします。
条件分岐のswitchノードと、ダッシュボード上でオン／オフをトグルで切り替えるためのswitchノード、changeノードを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/c5e5face-9999-e820-190a-e871183cc31f.png)
- 条件分岐のswitchノードはflow変数のsend_flagを判定するようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/f62e20cb-b65e-5374-206c-330c00d3adf9.png)
    
- changeノードでトグルのswitchノードの状態をセットするようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/0e2d76f6-ddd2-008c-9079-fe0508a28618.png)

トグルのchangeノードは設定不要です。

デプロイし、ダッシュボードを表示するとトグルでオン／オフが切り替えられるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/3f886745-18f9-63d7-3224-9245747ab627.png)

## APIを使った送信オン／オフ
前述の通り、今回のシステムはNode-REDをバックグラウンドで動かし、フロントのプログラムから指示を受けて動作を切り替えます。
そのため、APIでオン／オフを切り替えれるようにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/abb75e84-875c-ee9b-36bf-c191493edb5d.png)
    - オン／オフを切り替えるhttp inノードはURL（startとstop）を指定します。これによって（http://（IPアドレス):1880/api/startとhttp://（IPアドレス):1880/api/stop）で操作ができるようになります。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/0308d7d1-b698-657b-f21d-75e296373f82.png)
    - changeノードではトグルswitchノードに与える値（true/false）をセットします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/7a116c3e-9a27-3f81-6c46-9e5d687cffe1.png)
    - templateノードではAPIのレスポンスで返すJSON（今回はオン／オフをtrue／falseで返します）をセットします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/a0f20043-fc36-dfe7-1224-90e62942b831.png)

```json
{
    "switch" : "{{payload}}"
}
```
http responseノードは設定不要で、以上で実装は完了です。

# 動作確認
以下のHTMLをスマホでアクセスできる場所に置き、RedMobileを起動した状態でブラウザからスタートを押すと記録を開始し、ストップを押すと記録を停止するようになります。
```html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>WebUIコントローラ</title>
<script>
  function sendRequest(url) {
    fetch(url, { method: 'GET' })
      .then(response => response.text())
      .then(data => alert('応答: ' + data))
      .catch(error => alert('エラー: ' + error));
  }
  function start() {
    const id = document.getElementById('idInput').value;
    const url = `http://127.0.0.1:1880/api/start`;
    sendRequest(url);
  }
  function stop() {
    const url = 'http://127.0.0.1:1880/api/stop';
    sendRequest(url);
  }
</script>
</head>
<body>
<h1>コントロールパネル</h1>
<div>
  <button onclick="start()">スタート</button>
</div>
<div>
  <button onclick="stop()">ストップ</button>
</div>
</body>
</html>
```
<b>※このHTMLはChatGPTに作ってもらいました。すごい時代だ！</b>

# まとめ
[別の記事](https://qiita.com/ozk009/items/86f198c001a914cac9e7)でも書きましたが、このプロトタイプは@tatsuya1970 さんにハッカソンにお誘いいただいたことで、作成のきっかけをいただきました。

残念ながら1次審査通過ならずでしたが、今回の記事を書くきっかけとなりました。
このアドベントカレンダー含め、アウトプットの機会をいただき、感謝の極みです。

あまり胸を張って出せる内容とはなりませんでしたが、どなたかの参考になれば幸いです。
引き続き[Node-REDのアドベントカレンダー](https://qiita.com/advent-calendar/2023/node-red)をお楽しみください。