【ESP32】 ESP32の位置情報をFlutterで反映させてみた

image

ESP32と今回の開発環境について紹介

ESP32とは

Wi-FiとBluetoothを内蔵する低コスト、低消費電力なマイクロコントローラです。

他のデバイスを付けることで機能を拡張することもできます!

今回はGPSキットを利用します!

サイズは手のひらサイズほどです。今回はこちらを使っていきます

開発環境

今回はVSCodeのPlatformIOを利用します。

  • VSCode 1.73.1
  • C++ 1.13.7
  • Flutter 3.3.9
  • Dart 2.18.5

今回やること

  • 開発の準備
  • GPSキットを使いESP32の位置情報を取得する
  • GPSで取得した値をFirestoreに入れる
  • Firestoreの値を取得しMap表示させる

開発の準備

プロジェクトの作成

PlatformIOはVSCodeの拡張機能のところで検索すると出てくるのでインストールしてください。 アリのようなアイコンが目印です! インストールが完了したらHomeからNewProjectの作成をしましょう 今回はESP32を活用するのでBoardの部分を Adafruit ESP32 Feather を選択しましょう 最後にFinishを選択してプロジェクトを作成してプロジェクトを作成します!

Firebaseの作成

Firebaseのプロジェクト作成はHPの方でできますので分かりやすい名前で作成してください。 Firebaseのサイトはこちら(https://firebase.google.com/)

これで準備は完了です!続いてはGPSキットで位置情報の取得していきましょう!

GPSキットを使いESP32の位置情報を取得する

#include <TinyGPS++.h>

TinyGPSPlus gps;
HardwareSerial ss(2);
double Lat;
double Lng;

void setup()
{
    Serial.begin(115200);
    ss.begin(9600);
}

void loop()
{
    while(ss.available() > 0){
        char c = ss.read();
        gps.encode(c);
        if(gps.location.lat()){
            Lat = gps.location.lat();
            Lng = gps.location.lng();
    }
}

TinyGPSPlusというLiblaryを使って位置情報取得に成功しました! Latが緯度 Lngが経度を取得しています。 (思っていたよりも簡単?なのか?)

GPSで取得した値をFirestoreに入れる

Libraryを追加する

HomeのLibraliesでFirebase Arduino Client Library for ESP8266 and ESP32をプロジェクトに追加しましょう そして今回はPlatformIOが提供しているExamplesの中からコードを一部引用して作成していきます。 VSCodeよりもホームページの方が探しやすいのでページをこちらから移動します。 ExamplesからFirestore/CommitDocument/AppendArray/AppendArray.inoを今回は使用していきます。

ESP32側の全体のコード

#if defined(ESP32)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#endif
#include <Firebase_ESP_Client.h>
#include <TinyGPS++.h>
#include <addons/TokenHelper.h>
#include<string>

#define WIFI_PASSWORD //利用したいWiFiの設定

#define API_KEY //FirebaseプロジェクトからAPIkeyを取得

#define FIREBASE_PROJECT_ID //FirebaseのプロジェクトからIDを取得

#define USER_EMAIL "esp32@gmail.com"
#define USER_PASSWORD "esp32_test"

FirebaseData fbdo;

FirebaseAuth auth;
FirebaseConfig config;

unsigned long dataMillis = 0;
int count = 0;

TinyGPSPlus gps;
HardwareSerial ss(2);
double Lat;
double Lng;

void setup()
{
    Serial.begin(115200);
    ss.begin(9600);
    
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    Serial.print("Connecting to Wi-Fi");
    while (WiFi.status() != WL_CONNECTED)
    {
        Serial.print(".");
        delay(300);
    }
    Serial.println();
    Serial.print("Connected with IP: ");
    Serial.println(WiFi.localIP());
    Serial.println();

    Serial.printf("Firebase Client v%s\n\n", FIREBASE_CLIENT_VERSION);

    config.api_key = API_KEY;

    auth.user.email = USER_EMAIL;
    auth.user.password = USER_PASSWORD;

    config.token_status_callback = tokenStatusCallback; // see addons/TokenHelper.h

#if defined(ESP8266)
    fbdo.setBSSLBufferSize(2048 /* Rx buffer size in bytes from 512 - 16384 */, 2048 /* Tx buffer size in bytes from 512 - 16384 */);
#endif
    fbdo.setResponseSize(2048);

    Firebase.begin(&config, &auth);

    Firebase.reconnectWiFi(true);
}

void loop()
{
    while(ss.available() > 0){
        char c = ss.read();
        gps.encode(c);
        if(gps.location.lat()){
            Lat = gps.location.lat();
            Lng = gps.location.lng();
        }
    }
    if (Firebase.ready() && (millis() - dataMillis > 60000 || dataMillis == 0))
    {
        dataMillis = millis();
        
        String documentPath = "esp32/gps";

        FirebaseJson content;

        content.set("fields/lat/doubleValue", String(Lat,6));
        content.set("fields/lng/doubleValue", String(Lng,6));

        if(Firebase.Firestore.patchDocument(&fbdo, FIREBASE_PROJECT_ID, "", documentPath.c_str(), content.raw(), "")){
            Serial.printf("ok\n%s\n\n", fbdo.payload().c_str());
            return;
        }else{
            Serial.println(fbdo.errorReason());
        }

        if(Firebase.Firestore.createDocument(&fbdo, FIREBASE_PROJECT_ID, "", documentPath.c_str(), content.raw())){
            Serial.printf("ok\n%s\n\n", fbdo.payload().c_str());
            return;
        }else{
             Serial.println(fbdo.errorReason());
        }
    }
}

先ほどCopyしたExampleとほとんど変わりません。 自分が取得したい値をcontent.set()の部分に入れればとりあえずFirestoreに値を入れることができます。 APIkeyとProjectIDはFirebaseのプロジェクトのプロジェクト設定から確認することができます。 USER_EMAILの部分はFirebaseのFireAuthを活用して作成してください 実際に実行するとFirestoreにはこのように値が出力されます。 ここまできたら後もう一踏ん張りですね! こちらのサイトから関数の説明を見ることができます。(https://github.com/mobizt/Firebase-ESP-Client)

Firestoreの値を取得しMap表示させる

Flutter側全体のコード

こちらもgoogle_maps_flutterのExampleを利用しましたgoogle_maps_flutter(https://pub.dev/packages/google_maps_flutter)

import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  double Lat = 0;
  double Lng = 0;
  var esp32 = CameraPosition(
    target: LatLng(0, 0),
  );
  final Completer<GoogleMapController> _controller =
      Completer<GoogleMapController>();
  Future<void> _goToesp32() async {
    final GoogleMapController controller = await _controller.future;
    controller.animateCamera(CameraUpdate.newCameraPosition(esp32));
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: GoogleMap(
        mapType: MapType.hybrid,
        initialCameraPosition: CameraPosition(
          target: LatLng(40.7127753, -74.0059728),
          zoom: 14.4746,
        ),
        onMapCreated: (GoogleMapController controller) {
          _controller.complete(controller);
        },
      ),
      floatingActionButton: FloatingActionButton.extended(
        onPressed: () async {
          final values = await FirebaseFirestore.instance
              .collection('esp32')
              .doc('gps')
              .get();
          setState(() {
            Lat = values['lat'];
            Lng = values['lng'];
          });
          esp32 = CameraPosition(target: LatLng(Lat, Lng), zoom: 14);
          _goToesp32();
        },
        label: const Text('場所確認'),
      ),
    );
  }
}

実行すると次のようになりfloatingActionButtonを押すことでesp32の位置情報を取得することができます! 僕は熊本から可茂ITのインターンをしているので熊本市が表示されています

まとめ

今回はESP32に内蔵されているWiFi機能と追加でつけたGPS機能を利用してデバイスの位置情報取得アプリを作成しました 実用化できるかは分かりませんが総額でも2000円もしないくらいで作成できるので気になる方は試してみてください!

お知らせ

3月19日開催のアプリ開発講座の参加者募集中!!

3月19日開催のアプリ開発講座の参加者募集中!!

3月19日にアプリ開発講座を開催します!会場は岐阜県美濃加茂市のコワーキングスペース「こやぁね」です。興味のある方は是非ご参加ください!

Read More
可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。

Read More

タグ

Flutter (70)初心者向け (22)イベント (15)Nextjs (8)Google Apps Script (7)可茂IT塾 (6)Firebase (6)React (5)新卒 (3)就活 (3)給与支払報告書 (3)riverpod (3)Dart (3)JavaScript (3)TypeScript (3)インターン (3)FlutterWeb (2)画像 (2)アプリ開発 (2)React Hooks (2)tailwindcss (2)ワーケーション (2)社会人 (2)大学生 (2)お知らせ (2)webfeed (1)RSS (1)CodeRunner (1)VSCode (1)個人開発 (1)設計 (1)フルリモート (1)学生向け (1)Java (1)Spring Boot (1)エンジニア (1)DeviceOrientation (1)正規表現 (1)神楽 (1)趣味紹介 (1)プログラミングだけではない可茂IT塾のメンバー (1)線型計画法 (1)事例 (1)PreferredSize (1)マテリアルデザイン (1)Material (1)クパチーノデザイン (1)Cupertino (1)ListView (1)就活浪人 (1)既卒 (1)保守性 (1)シェアハウス (1)スクレイピング (1)Gmail (1)Googleグループ (1)GoogleWorkspace (1)ShaderMask (1)google map (1)Google Places API (1)Vercel (1)Google Domains (1)branch (1)Git (1)オンラインオフィス (1)Freezed (1)アイコン (1)Apple Store Connect (1)FlutterGen (1)検索機能 (1)Navigator (1)メール送信 (1)カスタム認証 (1)アニメーション (1)FloatingActionButton (1)Arduino (1)ESP32 (1)経験談 (1)フリーランス (1)Dialog (1)Figma (1)デザイン (1)Slack (1)BI (1)非同期処理 (1)BackdropFilter (1)iOS (1)レビュー (1)getAuth (1)匿名 (1)Algolia (1)chakra-ui (1)コンサルティング (1)Symbol (1)reactive_forms (1)

お知らせ

3月19日開催のアプリ開発講座の参加者募集中!!

3月19日開催のアプリ開発講座の参加者募集中!!

3月19日にアプリ開発講座を開催します!会場は岐阜県美濃加茂市のコワーキングスペース「こやぁね」です。興味のある方は是非ご参加ください!

Read More
可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。

Read More