Skip to content

Instantly share code, notes, and snippets.

@ksasao
Last active October 13, 2024 11:31
Show Gist options
  • Select an option

  • Save ksasao/0431fb4e2eb8cdacd42427589632d41e to your computer and use it in GitHub Desktop.

Select an option

Save ksasao/0431fb4e2eb8cdacd42427589632d41e to your computer and use it in GitHub Desktop.
M5Stack + LANモジュールでBLEビーコンのアドバタイジングパケットを受信してMQTTで送信するサンプル
#include <M5Stack.h>
//#include <M5_Ethernet.h>
#include <Ethernet2.h> // Please also fix Server.h according to https://twitter.com/ksasao/status/1845423873313079331
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <PubSubClient.h>
#include <WiFiClient.h>
#include <ArduinoUniqueID.h>
#define SCK 18
#define MISO 19
#define MOSI 23
#define CS 26
// MQTT Broker settings
const char* mqtt_broker = "192.168.3.18"; // 接続先 MQTT Broker の IPアドレス
String mqtt_topic; // MQTTのTopic名。setup()で初期化する。
IPAddress ip(192, 168, 3, 88); // M5Stack側の静的IPアドレス
byte mac[] = { UniqueID[0], UniqueID[1], UniqueID[2],UniqueID[3], UniqueID[4], UniqueID[5] };
// M5StackのLANモジュールのMACアドレスは初期状態では未設定のため利用者が設定する必要がある。
// 他のデバイスとぶつからないようにするため、ここではESP32のUniqueIDを流用。
// arp -a などでIPアドレスとの紐づけを確認できる
// MQTTのClientId生成用
const char hex[17]="0123456789ABCDEF";
char id[100];
String clientId;
// ESP32のチップごとに割り当てられた固有のIDをclientIDとして利用
String createClientId(){
id[UniqueIDsize*2]='\0';
for(size_t i = 0; i < UniqueIDsize; i++){
id[i*2] = hex[UniqueID[i] >> 4];
id[i*2+1] = hex[UniqueID[i] & 0xF];
}
String clientId = String((char*) id);
return clientId;
}
EthernetClient ethClient;
PubSubClient client(ethClient);
void setup() {
// M5Stack初期化
M5.begin(true, false, true);
M5.Power.begin();
// LANモジュール初期化
SPI.begin(SCK, MISO, MOSI, -1);
Ethernet.init(CS);
Ethernet.begin(mac, ip);
// MQTT初期化
clientId = createClientId();
mqtt_topic = "ble/" + clientId;
client.setServer(mqtt_broker, 1883);
// IPアドレスを表示
Serial.println(Ethernet.localIP());
M5.Lcd.clear();
M5.Lcd.setTextSize(2);
M5.Lcd.print("Topic : ");
M5.Lcd.println(mqtt_topic);
M5.Lcd.print("IPAddr: ");
M5.Lcd.print(Ethernet.localIP());
// BLE初期化
BLEDevice::init("");
}
void loop() {
// ネットワーク接続状態の確認と再接続
bool connected = true;
if (!client.connected()) {
connected = reconnect();
}
client.loop();
// BLEビーコンのスキャン
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setActiveScan(true);
BLEScanResults foundDevices = pBLEScan->start(1); // スキャン間隔1秒
// macアドレス順に結果がソートされている
int pos = 0;
for (int i = 0; i < foundDevices.getCount(); i++) {
BLEAdvertisedDevice device = foundDevices.getDevice(i);
String macAddress = device.getAddress().toString().c_str();
int rssi = device.getRSSI();
// 他のビーコンも飛んでいることが想定されるので適宜フィルタする
if (macAddress.startsWith("c1:c0")) { // ビーコン本体にMACアドレズが印字されているのでそれを参照した
// MQTTで受信したアドバタイジングパケットのMAC AddressとRSSIを送信
String payload = "{\"Id\":\"" + macAddress + "\",\"Value\":" + String(rssi) + "}";
Serial.print(mqtt_topic);
Serial.print(" ");
Serial.println(payload);
// 画面表示の更新
String view = macAddress + " " + String(rssi) + " ";
M5.Lcd.setCursor(0, (pos+2)*16);
M5.Lcd.print(view);
pos++;
if(connected){
client.publish(mqtt_topic.c_str(), payload.c_str());
}
}
}
}
// MQTT Broker 再接続処理。再接続できない場合には false を返して続行する。
bool reconnect() {
bool connected = client.connected();
if (!connected) {
Serial.print("Attempting MQTT connection (");
Serial.print(clientId);
Serial.println(")");
if (client.connect(clientId.c_str())) {
Serial.println("connected");
connected = true;
} else {
Serial.print("failed, rc=");
Serial.println(client.state());
connected = false;
}
}
return connected;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment