/*
 * Xiaoxiang BMS to MQTT via WiFi
 * by Bas Vermulst - https://github.com/BeaverUI/ESP32-BluetoothBMS2MQTT
 *
 * Based on original work from https://github.com/kolins-cz/Smart-BMS-Bluetooth-ESP32/blob/master/README.md
 *

   === configuring ===
   Using the #define parameters in the CONFIGURATION section, do the following:
   1) configure WiFi via WIFI_SSID and WIFI_PASSWORD
   2) configure MQTT broker via MQTTSERVER
   3) set unique node name via NODE_NAME
   4) ensure the BMS settings are OK. You can verify the name and address using the "BLE Scanner" app on an Android phone.


   === compiling ===
   1) Add ESP-WROVER to the board manager:
   - File --> Preferences, add to board manager URLs: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
   - Then, Tools --> Board --> Board manager... --> install ESP32 package v2.0.3 or later.


   2) Install required libraries:
   - MQTT (by Joel Gaehwiler)
   Install via "Manage Libraries..." under Tools.

   3) Configure board:
   Select Tools --> Board --> "ESP32 Arduino" --> "ESP WRover module"

   4) Connect board via USB.

   5) Configure programming options:
   Select appropriate programming port under Tools --> Port
   Select correct partitioning: 1.9MB app (with OTA) or 2MB app with 2 MB SPIFFS - otherwise it won't fit

   6) Program and go!

 */

// ==== CONFIGURATION ====
// BMS
#define BMS_MAX_CELLS 15 // defines size of data types
#define BMS_POLLING_INTERVAL 10*60*1000 // data output interval (shorter = connect more often = more battery consumption from BMS) in ms

// BLE
#define BLE_MIN_RSSI -75 // minimum signal strength before connection is attempted
#define BLE_NAME "BMS 1.1" // name of BMS
#define BLE_ADDRESS "70:e3:97:d2:b0:bb" // address of BMS

#define BLE_SCAN_DURATION 1 // duration of scan in seconds
#define BLE_REQUEST_DELAY 500 // package request delay after connecting - make this large enough to have the connection established in ms
#define BLE_TIMEOUT 10*1000 // timeout of scan + gathering packets (too short will fail collecting all packets) in ms

#define BLE_CALLBACK_DEBUG true // send debug messages via MQTT & serial in callbacks (handy for finding your BMS address, name, RSSI, etc)

// ==== MAIN CODE ====
#include "datatypes.h" // for brevity the BMS stuff is in this file
#include <BLEDevice.h> // for BLE

#include <driver/adc.h> // to read ESP battery voltage
#include <rom/rtc.h> // to get reset reason


// Init BMS
static BLEUUID serviceUUID("0000ff00-0000-1000-8000-00805f9b34fb"); //xiaoxiang bms service
static BLEUUID charUUID_rx("0000ff01-0000-1000-8000-00805f9b34fb"); //xiaoxiang bms rx id
static BLEUUID charUUID_tx("0000ff02-0000-1000-8000-00805f9b34fb"); //xiaoxiang bms tx id

const byte cBasicInfo = 3; //datablock 3=basic info
const byte cCellInfo = 4;  //datablock 4=individual cell info
packBasicInfoStruct packBasicInfo;
packCellInfoStruct packCellInfo;
unsigned long bms_last_update_time=0;
bool bms_status;
#define BLE_PACKETSRECEIVED_BEFORE_STANDBY 0b11 // packets to gather before disconnecting

// Other stuff
float battery_voltage=0; // internal battery voltage
String debug_log_string="";
hw_timer_t * wd_timer = NULL;

void debug(String s){
    Serial.println(s);
}

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


// === Main stuff ====
void loop(){
    bleGatherPackets();
}

/*
  mqttclient.publish(GetTopic("ip"), IPAddressString(WiFi.localIP()));
  mqttclient.publish(GetTopic("free-heap"), String(ESP.getFreeHeap()));
  mqttclient.publish(GetTopic("maxalloc-heap"), String(xPortGetMinimumEverFreeHeapSize()));
  mqttclient.publish(GetTopic("ssid"), WiFi.SSID());
  mqttclient.publish(GetTopic("rssi"), String(WiFi.RSSI()));

  mqttclient.publish(GetTopic("reset-reason"), String(GetResetReason(0)) + String(" | ") + String(GetResetReason(1)));

  mqttclient.publish(GetTopic("runtime"), String(millis()/1000));
  mqttclient.publish(GetTopic("battery-voltage"), String(battery_voltage,2));

  mqttclient.publish(GetTopic("bms-status"), String(bms_status));
  mqttclient.publish(GetTopic("bms-status-age"), String( (millis()-bms_last_update_time)/1000 ));

  if(bms_status){
    mqttclient.publish(GetTopic("number-of-cells"), String(packCellInfo.NumOfCells));
    mqttclient.publish(GetTopic("current"), String((float)packBasicInfo.Amps / 1000,2));
    mqttclient.publish(GetTopic("voltage"), String((float)packBasicInfo.Volts / 1000,2));
    if(packCellInfo.NumOfCells != 0){
      mqttclient.publish(GetTopic("cell-voltage"), String((float)packBasicInfo.Volts /(1000*packCellInfo.NumOfCells), 2));
    }
    mqttclient.publish(GetTopic("cell-diff"), String((float)packCellInfo.CellDiff, 0));
    mqttclient.publish(GetTopic("soc"), String((float)packBasicInfo.CapacityRemainPercent,1));

    mqttclient.publish(GetTopic("temperature-1"), String((float)packBasicInfo.Temp1 / 10,1));
    mqttclient.publish(GetTopic("temperature-2"), String((float)packBasicInfo.Temp2 / 10,1));
  }

  MqttPublishDebug();

  mqttclient.loop();
}

*/
