LoginSignup
11
1

More than 1 year has passed since last update.

M5StackをソラコムにつないでUIFlow(MicroPython)のコードをOTA実行する(ライブラリとサンプルコード付き)

Last updated at Posted at 2022-12-14

この記事は SORACOM Advent Calendar 2022 の 14 日目の記事です。前日の記事はソラコムCREのkanuによる「SORACOM Peek の使いどころ 3 選」でした。

はじめに

ごきげんよう。爬虫類(特にヘビ)は苦手なソラコムCREの岡田(hisaya)です。

「ヘビ嫌いだからPythonも嫌い」という非常にくだらない理由でPythonのプロジェクトや実装を避けてきたのですが、最近になってインタプリタ型言語の便利さを体感し、MicroPythonに興味を持つようになりました。
この記事ではマイクロな爬虫類、もといMicroPythonで記述されたUIFlowのコードをSORACOMプラットフォーム上に配置・ダウンロードし、M5Stack Core 2上で動作しているUIFlow環境で実行する方法をご紹介します。

この記事のOTAとは、セルラー通信経由で実行するアプリケーション(MicroPythonスクリプト)を取得し実行することを意味します。
SIMカードに対するOTA操作とは異なります。

用意するもの

なお、検証はしていませんが本質的にはESP32で動作するMicroPython環境とUnitとに搭載されている通信モジュール(SIMCOM SIM7080G)の組み合わせによるものなので、M5StickCやM5Stamp向けのモジュールでも動作するかもしれません。

ステップ

大まかに実行までの手順を以下に示します。

m5burnerでUIFlowを書き込む

M5StackにUIFlowを書き込みます。今回は最新版のUIFlow v1.11.0を使用します。
スクリーンショット 2022-12-14 9.17.52.png

ドライバをファイルシステムに転送する

実はUIFlowにはCatM+GNSS Unit向けのコードブロックも用意されているのですが、プロトタイプとして使ってみたところ以下のような問題がありました。

  • APN設定などのコードブロックがない
  • HTTP リクエストで対応しているメソッドがGETとPOSTしかない
  • リクエストは飛んでいるようだが、レスポンスの取得に失敗することが多い
  • 取得に失敗しても、どの段階で失敗したか分かりにくい

参考にしたいくつかの記事でもUART経由で直接ATコマンドを送受信するケースが多く見受けられたので、今回はMicroPythonでATコマンドを送受信する関数とSIM7080GでHTTP通信をするための最低限の関数をスクラッチ実装しました。
これによってUIFlowのコードブロックからATコマンドを直接送信することがなくなり、後述するUIFlowのコードブロック定義を併用することで見通しのよいビジュアルプログラムを作成できるようになりました。また通信に関しても、安定的にデータ取得やエラーハンドリングがしやすい状態になったと考えています。

実装した関数はリポジトリに配置してありますので、試してみたい方はチェックアウトのうえでUIFlowのターミナル画面から mpy/at_cmd.pympy/sim7080g.py ファイルを転送します。
ファイルの転送は、Terminalウインドウから「Select」ボタンで対象のファイルを選択し、「Send」ボタンをクリックすることで実行されます(転送は1件ごとに実行する必要があります)。
スクリーンショット 2022-12-14 9.27.16.png

コードブロックのインポート

上記で作成したライブラリを利用する形で、UIFlow上に配置可能なコードブロック定義も用意しました。UIFlowのCustomブロックタブから Import *.m5b を選択し、チェックアウトしたディレクトリに含まれる uiflow/MODEM_SIM7080G.m5b ファイルをインポートします。
スクリーンショット 2022-12-14 10.34.11.png

InitializeブロックはUARTやインポートしたモジュールインスタンスの生成のため必須になります。

SORACOM プラットフォーム側の設定

いったんUIFlowの画面を離れ、ソラコムのユーザーコンソールでCatM+GNSS Unitに挿入しているSORACOM IoT SIMの設定をしていきます。

SIM グループ設定

接続に利用するSIMカードのグループ設定を適用します。具体的には、SIMの情報や設定されているタグなどの情報にアクセスするメタデータサービスとSORACOM Harvest Filesを有効化しておきます。

SORACOM Harvest FilesへのMicroPythonコードのアップロード

ユーザードキュメントを参考にSORACOM Harvest Filesを有効化します。ファイルはユーザーコンソールからもアップロードできますので、適切な階層配下にプログラムを配置しておきます。
スクリーンショット 2022-12-14 10.52.28.png

たとえば、rgb-led.py は以下のような内容が記述されています。

from m5stack import *
import time
import random

print("Hello, I am user Python script from Metadata Service!")
rgb.setBrightness(100)

while True:
  rgb.setColorFrom(1, 5, (random.randint(0, 255) << 16) | (random.randint(0, 255) << 8) | (random.randint(0, 255)))
  time.sleep(0.5)

SIMタグの設定

こちらもユーザードキュメントを参考に設定していきます。タグはユーザーコンソールのSIM管理画面から対象のSIMを選択し「SIM詳細」画面から設定します。
スクリーンショット 2022-12-14 10.54.08.png

コードブロックの配置

リポジトリに同梱しているサンプルでは、以下のような流れで通信を実施しています。

  • メタデータサービス経由でSIMに設定されたタグ情報の取得(GET)
  • メタデータサービスを経由で特定のSIMタグの値を更新(PUT)
  • SORACOM Harvest Filesに配置したMicroPythonコードのダウンロードと実行

スクリーンショット 2022-12-14 9.30.30.png

重要な部分のMicroPythonコードを下記に示します(全文はこちら)。
SIMが挿入されていれば特にIDやパスワードなどを設定することなくセキュアに通信できることもセルラー通信のメリットの一つです。

# Describe this function...
def get_metadata_tags():
  global update_tag_name, update_tag_value, dl_path, http_results, tag_request_body, http_request_body, temp, script
  http_results = modem.http_request("GET", url='http://metadata.soracom.io', path='/v1/subscriber.tags', headers=None, params=None, body=None)
  return json.loads((http_results['response']))

# Describe this function...
def update_sim_tag(update_tag_name, update_tag_value):
  global dl_path, http_results, tag_request_body, http_request_body, temp, script
  tag_request_body = []
  tag_request_body.insert(0, {'tagName':update_tag_name,'tagValue':update_tag_value})
  http_request_body = json.dumps(tag_request_body)
  http_results = modem.http_request("PUT", url='http://metadata.soracom.io', path='/v1/subscriber/tags', headers={'Content-type':'application/json'}, params=None, body=http_request_body)
  return http_results['status_code']

# Describe this function...
def dl_from_harvest_files(dl_path):
  global update_tag_name, update_tag_value, http_results, tag_request_body, http_request_body, temp, script
  http_results = modem.http_request("GET", url='http://harvest-files.soracom.io', path=dl_path, headers=None, params=None, body=None)
  print((str('Download status: ') + str((http_results['status_code']))))
  return http_results['response']

import machine
from sim7080g import SIM7080G

uart_modem = machine.UART(1, rx=13, tx=14)
uart_modem.init(115200, bits=8, parity=None, stop=1)

modem = SIM7080G(uart_modem)
temp = modem.deactivate(0)
if temp:
  CONN.set_text('...')
else:
  CONN.set_text('ERR')
modem.setAPN("soracom.io", "sora", "sora")
temp = modem.activate(0)
if temp:
  CONN.set_text('OK')
else:
  CONN.set_text('ERR')
print(modem.isNetworkActivated(0))
temp = get_metadata_tags()
print((str('[CURRENT SIM TAGS]') + str(temp)))
if len(temp) != 0:
  GET_TAG.set_text('OK')
else:
  GET_TAG.set_text('NG')
temp = update_sim_tag('TAGS_FROM_DEVICE', str((rtc.printRTCtime())))
print((str('[UPDATE SIM STATUS] ') + str(temp)))
if temp == 200:
  PUT_TAG.set_text('OK')
else:
  PUT_TAG.set_text('NG')
script = dl_from_harvest_files('/uiflow/codes/unit-co2-demo.py').decode()
print((str('[PYTHON SCRIPT]') + str(script)))
if len(script) != 0:
  MSG.set_text('Executing script...')
else:
  MSG.set_text('Failed to DL!!')
print('Execute!')
exec(script)

実行

UIFlowのRunボタンをクリックしてM5Stackに通信とファイル読み込み用のプログラムを転送すると、セルラー通信の開始やタグ取得・更新処理を実施した後、SORACOM Harvest Filesからダウンロードしたプログラムをexec関数に渡して実行しています。
転送したファイルが上記サンプルコードの場合は、M5Stack本体右側のLEDがランダムな色で点滅すれば成功です。

PXL_20221214_054915506.jpg

現状のサンプルでは、OTAで読み込んだ(無限ループを含む)プログラムの実行後はM5Stack本体をリセットしないとファイル転送などに反応しなくなります。
タイマー割り込みで通信処理と実行処理を分けたりすることで回避できるかもしれません。

応用例

さまざまなユースケースが考えられるのですが、ここではいくつかの実装例を紹介します。

センサデータの表示

UIFlowで実装・生成したMicroPythonコードを実行できるので、画面表示や用意されているセンサ用ドライバもそのまま利用できます。
PXL_20221212_163443526.TS_exported_54064_1670863617139_2.jpg

画像データの表示

画像ファイル(PNGファイル)をダウンロードしてSDカード上に永続化し、画面に表示させる例です。リサイズなどは必要になると思いますが、ライブカメラの画像などを表示させるといった用途に使えるかもしれません。

PXL_20221212_163443526.TS_exported_26798_1670863609242_2.jpg

おわりに

サラッとOTA実行を推しにした記事ですが、内実のところはCat.M + GNSS UnitをはじめとしたSIM7080G通信モジュールのHTTPドライバやUIFlowコードブロックといった実装とその応用としての紹介でした。
Wi-Fiでいいというユースケースもあると思いますが、離れたところにあるM5Stackで動作する内容をサクッと書き換えることもできますし、コードブロックを利用してSORACOM Harvest Dataにセンサデータを送信するといった使い方も簡単にできるようになったと思います。
特にUIFlowではM5が販売する多くのモジュールが利用できますので、手頃なセンサやユニットなどと組み合わせてデータ取得やデバイスの制御などにも利用できます。ぜひこのスケッチや機構を利用・参考にしてIoTにトライしてみてください。

11
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
1