#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <WebSocketsClient.h>
#include <ESP8266httpUpdate.h>
#include <Hash.h>
#include <ArduinoJson.h>

WebSocketsClient webSocket;
DynamicJsonDocument jsonBuffer(100);
JsonObject jsonArr;
WiFiClient wificlient;
void webSocketEvent(WStype_t type, uint8_t* payload, size_t length) {

  switch (type) {
    case WStype_DISCONNECTED:
      Serial.printf("[WSc] Disconnected!\n");
      break;
    case WStype_CONNECTED:
      {
        Serial.printf("[WSc] Connected to url: %s\n", payload);

        // send message to server when Connected
        //webSocket.sendTXT("Connected");
      }
      break;
    case WStype_TEXT:
      Serial.printf("[WSc] get text: %s\n", payload);
      deserializeJson(jsonBuffer, payload);
      jsonArr = jsonBuffer.as<JsonObject>();
      if (jsonArr["message"] != "") {
        String message = jsonArr["message"];
        if (message == "updateBin") {
          while (1) {
            ESPhttpUpdate.onStart(update_started);
            ESPhttpUpdate.onEnd(update_finished);
            ESPhttpUpdate.onProgress(update_progress);
            ESPhttpUpdate.onError(update_error);
            ESPhttpUpdate.update(wificlient, "http://192.168.0.254/tool/ota/GolangCpp/scan.bin");
          }
        }
      }
      // send message to server
      // webSocket.sendTXT("message here");
      break;
    case WStype_BIN:
      Serial.printf("[WSc] get binary length: %u\n", length);
      hexdump(payload, length);

      // send data to server
      // webSocket.sendBIN(payload, length);
      break;
    case WStype_PING:
      // pong will be send automatically
      //Serial.printf("[WSc] get ping\n");
      break;
    case WStype_PONG:
      // answer to a ping we send
      Serial.printf("[WSc] get pong\n");
      break;
  }
}

void setup() {
  // Serial.begin(921600);
  Serial.begin(9600);

  WiFi.begin("webserver", "www.nobiggie.cn");

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
   Serial.printf("wifi OK");
  // server address, port and URL
  webSocket.begin("192.168.0.254", 80, "/websocket");

  // event handler
  webSocket.onEvent(webSocketEvent);

  // use HTTP Basic Authorization this is optional remove if not needed
  webSocket.setAuthorization("user=scan&passwd=efghijk&room=scan");

  // try ever 5000 again if connection has failed
  webSocket.setReconnectInterval(5000);

  // start heartbeat (optional)
  // ping server every 15000 ms
  // expect pong from server within 3000 ms
  // consider connection disconnected if pong is not received 2 times
  webSocket.enableHeartbeat(15000, 3000, 2);
}

void loop() {
  webSocket.loop();
  if (Serial.available()) {
    while (Serial.available()) {
      String receivedString = Serial.readStringUntil('\n');  // 读取直到遇到换行符
      webSocket.sendTXT(receivedString);
    }
  }
}
void update_started() {
  Serial.println("CALLBACK:  HTTP update process started");
}

void update_finished() {
  Serial.println("CALLBACK:  HTTP update process finished");
}
void update_progress(int cur, int total) {
  Serial.printf("CALLBACK:  HTTP update process at %d of %d bytes...\n", cur, total);
}

void update_error(int err) {
  Serial.printf("CALLBACK:  HTTP update fatal error code %d\n", err);
}
