見出し画像

【ミーア】FlutterとESP32を連携:おやすみモードの時間設定をAWS Device Shadow・MQTT経由で同期

前回の記事「眠りモードに至るまでの時間をアプリ側(Flutter)で設定して、サーバー側(Go)に反映させる。」では、ユーザーがアプリで設定した「おやすみモード」までの時間をサーバー側のユーザーデータベースに反映させる方法について記載した。

AWS Device ShadowとMQTTプロトコルについて

AWS Device Shadowとは

AWS Device Shadowは、IoTデバイスの状態をクラウド上に保存・同期するサービス。Device Shadowを使用すると、Deviceがオフラインの場合でもその最新の状態を保存しておくことができる。Deviceが再びオンラインになった時に、クラウド側のデータと同期を行い、デバイスの状態を最新のものに更新することが可能。

MQTT・トピックとは

MQTT(Message Queuing Telemetry Transport)は、軽量なメッセージングプロトコルで、ネットワーク帯域が限られた環境やリモートシステム間の通信に適している。IoTデバイス間の通信や、デバイスとサーバー間の通信によく使用される。

Publisher(送信者), Broker(仲介者), Subscriber(購読者)の3者がいて、PublisherがBroker経由で、Subscriber(1:1 or 1: 複数。選べる)にメッセージを送信する。

また、MQTTにはトピックという仕組みがある。トピックは、メッセージが送信される際に使用されるラベルのこと。

トピック名は、スラッシュ (/) 文字を使用して階層のレベルを区切ることにより、情報の階層を表すことができる。たとえば、このトピック名は、部屋 1 の温度センサーを表すことができる。

  • sensor/temperature/room1


実装概要:アプリ→サーバー→Device shadow→ESP32

アプリからのリクエストに応じて、デバイスシャドウを介してESP32デバイスの設定を更新するプロセスの概要。

アプリからの設定更新リクエスト:

ユーザーがアプリを通じて設定を更新すると、その更新リクエストはバックエンドサーバーを通じてAWS IoT Coreのデバイスシャドウのdesiredセクションに反映される。

デバイスシャドウのdesiredセクションの更新:

バックエンドサーバーは、受け取った設定更新リクエストに基づいてデバイスシャドウのdesiredセクションを更新する。このdesiredセクションは、デバイスに適用されるべき望ましい設定を表す。

ESP32デバイスへの通知:

デバイスシャドウのdesiredセクションが更新されると、その情報はMQTTメッセージとしてESP32デバイスに通知される。この通知は、デバイスシャドウの/update/deltaトピックを通じて送信される。

ESP32デバイスによる差分の取得:

ESP32デバイスは、/update/deltaトピックからメッセージを受け取り、その内容を解析して、desiredセクションとデバイスの現在の設定(reportConfig)との間の差分を取得する。

設定の同期と反映:

ESP32デバイスは、取得した差分に基づいて自身の設定を更新する。このプロセスでは、デバイスの現在の設定(reportConfig)がdesiredセクションに記述された設定に合わせて変更される。

更新後の状態の報告:

設定の更新が完了した後、ESP32デバイスは新しい設定をデバイスシャドウのreportedセクションに報告する。これにより、デバイスシャドウのreportedセクションはデバイスの実際の状態を正確に反映するようになる。

この手順に合わせて、実装していく。

実装:サーバー側(Go言語)

DeviceConfig 構造体に SleepTransitionTime フィールドを追加

この変更により、DeviceConfig 構造体には SleepTransitionTime フィールドが含まれるようになり、UserToDeviceConfig 関数では User インスタンスからこの新しいフィールドの値を DeviceConfig に反映させることができる。

SleepTransitionTime を含む新しいデバイス設定は、JSON形式で、デバイスの望ましい状態(desired state)を表す。更新されたDevice Shadowは、MQTTの通信プロトコルを使用してESP32にJSON形式で送信される。

// device_shadow.go
package clocky_be

import (
	"encoding/json"

	"github.com/EarEEG-dev/clocky_be/types"
)

type DeviceConfig struct {
	TalkFrequency           int                  `json:"talk_frequency"`
	BirthDate               types.NullDate       `json:"birth_date"`
	PhraseType              types.NullString     `json:"phrase_type"`
	TalkStartTime           types.NullHourMinute `json:"talk_start_time"`
	TalkEndTime             types.NullHourMinute `json:"talk_end_time"`
	WeatherAnnouncementTime types.NullHourMinute `json:"weather_announcement_time"`
	WorkStartTime           types.NullHourMinute `json:"work_start_time"`
	WorkEndTime             types.NullHourMinute `json:"work_end_time"`
	SleepTransitionTime     types.NullInt64      `json:"sleep_transition_time"` // 追加したフィールド
	Volume                  int                  `json:"volume"`
}

// ... 他の構造体と関数 ...

func UserToDeviceConfig(user *User) DeviceConfig {
	return DeviceConfig{
		TalkFrequency:           int(user.TalkFrequency.Int64),
		BirthDate:               user.BirthDate,
		PhraseType:              user.PhraseType,
		TalkStartTime:           user.TalkStartTime,
		TalkEndTime:             user.TalkEndTime,
		WeatherAnnouncementTime: user.WeatherAnnouncementTime,
		WorkStartTime:           user.WorkStartTime,
		WorkEndTime:             user.WorkEndTime,
		SleepTransitionTime:     user.SleepTransitionTime, // 新しいフィールドの値を設定
		Volume:                  int(user.Volume.Int64),
	}
}

// ... 他の関数 ...

続きは、こちらで記載しています。


この記事が参加している募集

仕事について話そう

よろしければサポートお願いします!いただいたサポートはクリエイターとしての活動費に使わせていただきます!