Itsukaraの日記

最新IT技術を勉強・実践中。最近はDeep Learningに注力。

人工衛星の回帰日数計算をGoogle Cloud Function化

背景

先日作った「人工衛星の回帰日数を計算するツール*1」を、Google Cloud Function化してみました。参考にしたのは、日本語のブログ記事*2と、Google Cloud Functionのドキュメント*3です。

Cloud Functionというのは、関数呼び出し的にGoogle Cloudを使うサービスで、仮想マシンやWebサーバーを用意しなくても、比較的軽い単発の処理を、HTTPリクエスト等で呼び出すことができます。

当方にとって一番うれしいのは、無料で使えることです。つまり、Google Cloud Platformの無料枠内で月に200万回呼び出し可能なことです*4

結果

下記が、回帰日数計算をCloud Functionとして利用するためのフォームです。


TLE (衛星名含めた3行。省略時はCOSMO-SkyMed-4のTLEを使用):

date[YYYY-MM-DD hh:mm:ss] (省略時は現在時刻を使用):

表示対象の、経度誤差の許容最大値[deg]:

Repeat Cycleの、経度誤差の許容最大値[Km]:


上記で人工衛星のTLEと日時を入力して、「Search Repeat Cycle」ボタンを押すと、例えば下記のような回帰日数計算結果が表示されます。
f:id:Itsukara:20180918020429p:plain

なお、ソースコードGithubにアップ済です*5

つでに、Cloud Functionを呼び出すためのページを、Firebaseに入れてみました。
Cloud FunctionのURLより短く、良いですね:https://repeat-cycle.firebaseapp.com/

苦労した点

データがCloud Functionに渡らない

問題

Cloud Functionは初めてのため、HTMLフォームからCloud Functionにデータ(TLEとdate)が渡せず、非常に苦労しました。Cloud Functionのページに書かれたテスト実行ではデータが渡るのですが、HTMLフォームからは渡らないというもの。

仮解決策

ChromeのDevToolのNetworkで調べたところ、データ自体はちゃんと送られている模様。また、手でURLを修正し、データをURLに直接埋め込むと、上手く行きます(例えば「URL?date=2018-09-17%2011:00:00」等)。

少し調べたところ、formのmethodとして、POSTの代わりにGETを使えば、データがURLに埋め込まれるため、上手く行く模様*6。しかし、GETでは、データが長いとURLが長くなりすぎて、上手く行かない場合があるようです。また、ネットワーク上を生データが流れるので、お勧めできないようです。

本解決策に向けて

そこで、Cloud Functionの関数内に渡される引数「request」からデータを取り出す方法を工夫すれば良いのですが、これも、Cloud Functionのページに書かれたテストでは上手く行くものの、HTMLフォームからPOSTした場合は、値がうまく渡りません。

解決策

Webで、Cloud Function (Python版)の色々な使用例を調べたのですが、結局分からず、Cloud Functionのインターフェースとして使っているFlaskのドキュメントを調べることにより、解決することができました。コードとしては、下記の部分で、特に、request.formを使った部分は、Webでの記載例が見つかりませんでした。POSTで渡されるデータを受け取るには、この部分が必須でした。

request_json = request.get_json()
if request.args:
    if 'TLE' in request.args:
        TLE  = request.args.get('TLE')
    if 'date' in request.args:
        date = request.args.get('date')
elif request_json:
    if 'TLE' in request_json:
        TLE  = request_json['TLE']
    if 'date' in request_json:
        date = request_json['date']
else:
    if 'TLE' in request.form:
        TLE  = request.form['TLE']
    if 'date' in request.form:
        date = request.form['date']

計算結果が改行無しで表示される

問題

上記で、計算結果が表示されるようになったものの、結果が改行無しで表示されるため、非常に読みにくくなりました。
f:id:Itsukara:20180917181903p:plain

解決策

これに関しても、Flaskのドキュメントを調べることにより解決しました。Cloud Functionの戻り値として単に文字列を返す場合、結果のmimetypeが自動的にhtmlになるが原因でした。そこで、下記の様に、mimetypeを指定してResponseオブジェクトを返すことで、上手く表示されるようになりました。

return Response(text, mimetype='text/plain')