#include <M5Unified.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

const char* ssid = "ics-ap";
const char* password = "jikkenics";

const char* server = "mqtt.istlab.info";
const int   port   = 1883;   
const char* pubTopic = "+"; // 班名を入れれば他の班とかぶらない。+にはしない。ex. jikken/A4han

WiFiClient wifiClient;
char* clientid = "m5scp2_002"; //デバイス個別に設定すればなんでもよい
PubSubClient mqttClient(wifiClient); // MQTT Client

char macaddr[100];

void setup() {
  auto cfg = M5.config();
  cfg.serial_baudrate = 115200;
  M5.begin(cfg);
  M5.Display.setRotation(3); //横向き
  M5.Display.setFont(&fonts::lgfxJapanGothic_16);
  M5.Display.println("mqtt01sub");
  M5.Display.setTextScroll(true);

  WiFi.begin(ssid, password); // 接続開始
  while (WiFi.status() != WL_CONNECTED) { // 接続中...
    M5.Display.print(".");
    M5.delay(500);
  }
  // 接続完了！！
  M5.Display.fillScreen(BLUE);
  M5.Display.setCursor(0, 8, 4);//x,y,fonttype
  M5.Display.setTextColor(WHITE, BLUE);
  M5.Display.print("  Wifi Connected!\n");
  String gotip = WiFi.localIP().toString(); // m5デバイスのIPアドレス
  M5.Display.println(gotip);

  // 参考：WiFiデバイスのMACアドレスを取得し、送信する
  uint8_t mac[6];
  WiFi.macAddress(mac);
  sprintf(macaddr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
  M5.Display.println(macaddr);

  mqttClient.setServer(server, port);
  mqttClient.setCallback(callback_on_subscribe);

  if (!mqttClient.connected()) {
    Serial.println("Try (re)connecting...");
    reconnect();
  }
  mqttClient.subscribe(pubTopic);

  M5.delay(2000);
  Serial.println("自動的にsubscribeします。Serialと画面に出力します。");
  M5.Display.setFont(&fonts::lgfxJapanGothic_16);
  M5.Display.println("自動的にsubscribeします。Serialと画面に出力します。");
}

void loop() {
  mqttClient.loop(); // データがpublishされたら、callback_on_subscribe が呼ばれる
  M5.delay(50);
}

void reconnect() {
  while ( !mqttClient.connected() ) {
    if ( mqttClient.connect(clientid) ) {
      Serial.println("Connected to MQTT Broker.");
    } else {
      Serial.printf("Connect Failed. state=%d", mqttClient.state());
    }
  }
}

// データがPublishされたら、ここが実行される。（39行目でコールバック関数を設定しているため）
void callback_on_subscribe(char* topic, byte* payload, unsigned int len) {
  char buf[100];
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < len ; i++) {
    buf[i] = (char)payload[i];
  }
  buf[len] = 0;
  Serial.println(buf);
  M5.Display.println(buf);
  return;
  //  参考：JSON Parsing example
  //  StaticJsonDocument<200> sjdoc;
  //  deserializeJson(sjdoc, buf);
  //  int intval = sjdoc["intval"];
  //  const char* str = sjdoc["string"];
}