M5Stack Basicを使って、WiFiスキャンで得られるMACアドレス情報を元にGoogle Map上に現在位置をプロットするサンプルを作ってみました。
#WiFiスキャンでAPリストを取得する
まずは、WiFi networksをスキャンし、周辺のアクセスポイントを取得します。WiFi.hをインクルードしたうえでWiFi.scanNetworks();
でWiFiネットワークをスキャンします。戻り値として見つかったWiFiネットワークの数を返します。その後、スキャンされたネットワーク数でループし、channel(i)でチャネル、RSSI(i)で受信レベル、SSID(i)でSSIDを取得できますが、ここでは、MACアドレスを取得したいので、WiFi.BSSIDstr(i)
を使います。
int n = WiFi.scanNetworks(); //ネットワークをスキャンして数を取得
for (int i = 0; i < n; i++) {
String bssid = WiFi.BSSIDstr(i); //BSSID(MACアドレス)を文字列で取得
}
#Google Geolocation APIで位置情報を取得
得られたMACアドレスのリストを元に、Google Geolocation APIで位置情報(緯度経度)を取得します。
位置情報の取得は、下記のURLにPOSTすることになります。
https://www.googleapis.com/geolocation/v1/geolocate?key=YOUR_API_KEY
POST時に先ほどのMACアドレスのリストをJSONで渡すことになります。例えば、このようなJSONです。
{
"considerIp":"false",
"wifiAccessPoints":[
{"macAddress":"AA:AA:AA:AA:AA:AA"},
{"macAddress":"BB:BB:BB:BB:BB:BB"},
{"macAddress":"CC:CC:CC:CC:CC:CC"}
]
}
ArduinoでJSONを取り扱うにはArduinoJsonが便利です。
##ArduinoJsonライブラリのインストール
ArduinoJsonライブラリを使用するためには、Arduino IDEのライブラリマネージャでAruinoJsonをインストールしておく必要があります。
##JSONシリアライズ
ArduinoJsonでは、メモリ消費を極力抑えるために生成するJSONのサイズを指定しておく必要があります。上記のように3つのMACアドレスをJSONコードにする場合に必要なサイズを調べる必要がありますが、ArduinoJson Assistantを使いましょう。下図のように、Input欄に想定するJSONコードを入力すると、右側のMemory pool sizeにメモリ確保の記載例が出てきます。
今回の場合、3つの配列がそれぞれ1つずつの要素を持ち(wifiAccessPoints)、considerIpとあわせて2つの要素になるため、JSON_ARRAY_SIZE(3) + 3*JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2)
分の確保が必要になります。更に各要素の文字数を想定し、追加で121バイトを確保しておく必要があります。
下記にJSONシリアライズのサンプルを記載します。(あまり多くのMACアドレスを送るとコスト的にも無駄な場合もありますので、MAX_APで指定しておきます)
const int MAX_AP = 3
int n = WiFi.scanNetworks();
const size_t capacity = JSON_ARRAY_SIZE(MAX_AP) + (MAX_AP)*JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2) + 34 + (MAX_AP * 29);
DynamicJsonDocument doc(capacity);
doc["considerIp"] = "false";
JsonArray wifiAccessPoints = doc.createNestedArray("wifiAccessPoints");
for (int i = 0; i < n; i++) {
String bssid = WiFi.BSSIDstr(i);
JsonObject wifiAP = wifiAccessPoints.createNestedObject();
wifiAP["macAddress"] = WiFi.BSSIDstr(i);
if (i + 1 == MAX_AP) break;
}
serializeJson(doc, json);
##Google Geolocation APIにPOST
リクエストJSONが出来上がれば、Google Geolocation APIにPOSTします。
HTTPClientを使ったサンプルは以下の通りです。json_requestは先ほどシリアライズしたJSONコードです。
HTTPClient http;
http.begin("https://www.googleapis.com/geolocation/v1/geolocate?key=YOUR_API_KEY");
int status_code = http.POST(json_request);
if (status_code == 200) {
String json_response = http.getString();
const size_t capacity = 2*JSON_OBJECT_SIZE(2) + 30;
DynamicJsonDocument doc(capacity);
deserializeJson(doc, json_response);
float lat = doc["location"]["lat"];
float lng = doc["location"]["lng"];
float accuracy = doc["accuracy"];
}
http.end();
ここで、またしても、ArduinoJsonを使って、Google Geolocation APIから帰ってきたJSONをデシリアライズしています。
これで、緯度経度(と精度)が取得できました。
#Google Static Mapで現在位置をプロットする
最後にGoogle Map上に位置をプロットすることになりますが、M5Stackの画面上に静的画像として描画したいので、**Map Static API**を使います。このAPIは下記URLに必要なパラメータを渡せば、jpeg等の画像ストリームを取得できます。https://maps.googleapis.com/maps/api/staticmap?[parameters]&key=YOUR_API_KEY
指定可能なパラメータは、下記のようなものがあります。(参考)
パラメータ | 説明 | 例 |
---|---|---|
center | 地図の中心座標。「緯度,経度」または「住所」「建物名」なども指定可能です。 | 35.5000,136.5000、六本木ヒルズ |
zoom | マップのズームレベルを決定します。1~22を指定できます。 | 15 |
size | 地図画像のサイズ(幅×高さ)を決定します。M5Stackのディスプレイを考えると320x240が最適です。 | 320x240 |
format | 画像の形式を決定します。gif、jpg、png を指定できます。 | jpg |
maptype | 地図のタイプを決定します。roadmap, satellite, hybrid, terrain を指定できます。 | roadmap |
Static Mapの取得に成功すれば、**getStreamPtr()で画像ストリームを読み込んでいき、最後にM5.Lcd.drawJpg(...)**で画面描画をすることとなります。 | ||
以下にサンプルを示します。 |
HTTPClient http;
http.begin(url); //urlはパラメータ込みのGoogle Static APIへのURL
int status_code = http.GET();
if (status_code == 200) {
int len = http.getSize();
if (len > 0) {
WiFiClient * stream = http.getStreamPtr();
// read all data from server
uint8_t* p = buff;
int l = len;
while (http.connected() && (l > 0 || len == -1)) {
// get available data size
size_t size = stream->available();
if (size) {
int s = ((size > sizeof(buff)) ? sizeof(buff) : size);
int c = stream->readBytes(p, s);
p += c;
if (l > 0) {
l -= c;
}
}
}
}
M5.Lcd.drawJpg(buff, len);
}
http.end();
M5StackのdrawJpg関数については、こちらを参考にしてください。
#サンプルコード
今回の全サンプルコードはこちら(GitHub)上にあげておきます。Google Static Map用のAPI KeyやWiFi接続用のSSID、キーはご自身の環境にあわせてください。