LoginSignup
1
0

More than 1 year has passed since last update.

マイコンボードESP32でMicroPython環境構築からSwitchbotAPI操作まで

Last updated at Posted at 2022-11-26

はじめに

WiFiモジュールを搭載したマイコンモジュールの一つにESP32があります。
マイコン初心者の私が備忘録を兼ねて、Micropython環境の構築からSwitchbotAPIを操作するところまで書きます。
以下の流れです。

  1. ESP32 PC接続設定
  2. MicroPython環境構築
  3. ESP32 WiFi接続
  4. SwitchbotAPI操作

参考

MicroPython環境構築の参考にしました。
Zenn: Thonnyで、ESP32 - MicroPython環境を構築するよ

ネットワーク接続の参考にしました。ESP8266とありますが、ESP32でも使えるようです。
MicroPython: ESP8266 用クイックリファレンス

SwitchbotAPIのドキュメント
GitHub: OpenWonderLabs/SwitchBotAPI
ヘッダーの作成の参考にしました。
Qiita: [Switchbot API v1.1が登場] APIでSwitchBotロックを遠隔操作する

SwitchbotAPIの認証キーを生成する際に用いるmicropython-hmacではエラーがでて困りましたが、こちらを使えば解決しました。
GitHub: gloveboxes/ESP32-Micropython-Azure-IoT-and-Event-Hub-Client

環境

1. ESP32 PC接続設定

まずはESP32をUSB(microB-TypeA)ケーブルでPCに接続し、
「デバイスマネージャー」の「ポート(COMとLPT)」欄を開きます。
その中の「Silicon Labs CP210x USB to UART Bridge」末尾についているCOM~の番号を覚えておきます。

黄色の!が表示されている場合はドライバが入っていないので、Silicon Labs: CP210x USB to UART Bridge VCP Driversからドライバをダウンロードしインストールしてください。

ESP32とPCの接続はこれで完了です。

1_device_manager.png

2. MicroPython環境構築

参考ページに従って設定します。
MicroPythonのリンクからファームウェアをダウンロードします。

image.png

ホストPCにESP32にファームウェアを書き込むためのモジュールをインストールします。

pip install esptool

ESP32のROMを消去します。com~にはデバイスマネージャーで確認したポート番号を指定します。

esptool --port com5 erase_flash

ファームウェアのダウンロード先に作業ディレクトリを移動し、以下のコマンドを入力してESP32にファームウェアを書き込みます。

esptool --chip esp32 --port com5 write_flash -z 0x1000 esp32-20220618-v1.19.1.bin

Thonnyをインストールし起動します。
右下のインタプリタ設定から「MicroPython(ESP32)・COM~」を選択すれば準備は完了です。

image.png

3. ESP32 WiFi接続

ESP32を自宅のWiFiに接続します。以下のクイックリファレンスにESP8266とありますが、ESP32でもそのまま動きます。
MicroPython: ESP8266 用クイックリファレンス

def do_connect():
    import network
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        print('connecting to network...')
        wlan.connect('ssid', 'key') #ここに接続したいWiFiのSSIDとパスワードを書く
        while not wlan.isconnected():
            pass
    print('network config:', wlan.ifconfig()) #IPアドレス、ネットマスク、ゲートウェイ、DNS

接続が完了するとIPアドレス、ネットマスク、ゲートウェイ、DNSが表示されます。
簡単にマイコンのWiFi接続ができました。便利です。

network_connection.png

4. SwitchbotAPI操作

公式ドキュメントに従います。
SwitchbotAPIの操作の流れは以下の通りです。

  1. 認証のためのヘッダーを作成する
  2. Switchbotのデバイス一覧を取得し、操作したいデバイスのIDを確認する
  3. デバイスに対して操作を行う

4-1. 認証のためのヘッダーを作成する

Switchbotのスマホアプリの「設定」→「アプリバージョン」を項目を連続で10回タップすると「トークンを取得」ボタンが現れます。これを記録しておきます。

公式ドキュメントの「Authentication」項のサンプルプログラムと参考をもとにしました。
ホストPCではこのまま動きますが、ESP32で実行するためにはMicroPythonのデフォルトのライブラリにhmac, base64がないためモジュールの追加インストールが必要です。

import time
import hashlib
import hmac
import base64

# open token
token = '' # copy and paste from the SwitchBot app V6.14 or later
# secret key
secret = '' # copy and paste from the SwitchBot app V6.14 or later

def get_auth_header(token, secret):
    nonce = '' #空欄のままで良いらしい
    t = int(round((time.time() + 946684800) * 1000)) #後述 基準の時刻がホストPCとESP32で異なるため30年分の秒数を足す
    string_to_sign = '{}{}{}'.format(token, t, nonce)

    string_to_sign = bytes(string_to_sign, 'utf-8')
    secret = bytes(secret, 'utf-8')

    sign = base64.b64encode(hmac.new(secret, msg=string_to_sign, 
    digestmod=hashlib.sha256).digest())
    print ('Authorization: {}'.format(token))
    print ('t: {}'.format(t))
    print ('sign: {}'.format(str(sign, 'utf-8')))
    print ('nonce: {}'.format(nonce))

    header={}
    header["Authorization"] = token
    header["sign"] = str(sign, 'utf-8')
    header["t"] = str(t)
    header["nonce"] = nonce
    return header

ここで色々つまづきました。
MicroPython版のパッケージ管理モジュールupipでhmacをインストールし、上のプログラムのハッシュ化部分を実行すると以下のエラーがでます。

出力結果
Traceback (most recent call last):
  File "<stdin>", line 5, in <module>
  File "/lib/hmac.py", line 149, in new
  File "/lib/hmac.py", line 63, in __init__
AttributeError: 'sha256' object has no attribute 'digest_size'

困り果てましたが、GitHub: gloveboxes/ESP32-Micropython-Azure-IoT-and-Event-Hub-Clientからhashlib, base64.py, hmac.py, warnings.pyをESP32にインストールしたところ無事ハッシュ化できました。

これで認証ヘッダーの生成は完了です。

image.png

4-2. Switchbotのデバイス一覧を取得し、操作したいデバイスのIDを確認する

公式ドキュメントに従って、Switchbotデバイスの一覧を取得します。

host_domain = "https://api.switch-bot.com"
ver = "/v1.1"

def get_device_list(header):
    response = urequests.get(host_domain + ver + "/devices", headers=header)
    return_json = response.json()
    if return_json["message"] == "success":
        print("取得成功")
        return return_json["body"]
    elif return_json["message"] == "Unauthorized":
        print("認証エラー")
        return None
    else:
        print("エラー")
        return None

header = get_auth_header(token, secret)
device_list = get_device_list(header)
print(device_list)

ここで、ホストPCでAPIを操作したあとにESP32で同じことをしたら認証エラーがでました。
詳しく調べていませんが、ホストPCとESP32でtime.time()で得るエポック秒数が大きくずれていることが問題のようでした。
それぞれの基準時刻を取得します。

imoort time
time.gmtime(0)

ホストPCの基準時刻は1970/01/01 00:00:00です。

ホストPC 出力結果
time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)

一方でESP32の基準時刻は2000/01/01 00:00:00です。

ESP32 出力結果
(2000, 1, 1, 0, 0, 0, 5, 1)

両者の差の秒数を求めます。

import datetime
(datetime.datetime(2000,1,1,0,0,0) - datetime.datetime(1970,1,1,0,0,0)).total_seconds()
出力結果
946684800.0

以上からget_auth_header関数ではこの秒数を足しています。
これで今のところ問題は起こっていませんが、もっと良い対処法がありそうです。

get_auth_header(token, secret)
t = int(round((time.time() + 946684800) * 1000))

これでSwitchbotのデバイス一覧が取得できました。
操作したいデバイスのdeviceIdを控えておきます。

4-3. デバイスに対して操作を行う

ここではお試しで温湿度計の温度を取得してみます。

def get_th(header):
    th_deviceid = "" #デバイスIDを入力する
    response = urequests.get(host_domain + ver +"/devices/" + th_deviceid + "/status", headers=header)
    temperature = response.json()["body"]["temperature"]
    humidity = response.json()["body"]["humidity"]
    return temperature, humidity

header = get_auth_header(token, secret)
temperature, humidity = get_th(header)
print(f"室温:{temperature}℃  湿度{humidity}%")
出力結果
室温:25.1  湿度42%

無事に温度と湿度が取得できました。
他のデバイスの操作も公式ドキュメントを参考に行えます。

本文で使用したプログラムを以下にアップロードしました。

まとめ

タイトルの通り、マイコンボードESP32についてMicroPython環境構築からSwitchbotAPI操作まで行いました。いくつかの躓きがありましたが、最終的に温湿度計のデータを取得するところまで来ました。
なにかの役に立てば幸いです。

1
0
0

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
1
0