// Code for NodeMCU boards with Espressif 8266 WiFi controller
// for measuring temperature, humidity, and pressure using the BME280 module

#include <ESP8266WiFi.h>    // Include the Wi-Fi library
#include <ESP8266HTTPClient.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

// Some BME280 modules are strapped for address 0x76 - change line below as needed
#define I2C_ADDR 0x77

#define DELAYTIME 1000

Adafruit_BME280 bme;

// Wi-Fi settings - replace with your Wi-Fi SSID and password
const char* ssid     = "your-ssid";
const char* password = "your-wifi-password";

// IP address of server or Raspberry Pi running Machinechat JEDI software
// If you changed the JEDI port number, replace 8100 with the new port
const char* host = "192.168.1.7:8100";

// This is the setup section and will only run one time
void setup() {

  // Configure status LED on NodeMCU board
  // Later, it will be programmed to blink every HTTP POST
  pinMode(LED_BUILTIN, OUTPUT);

  // Configure serial port for debug when NodeMCU board is connected
  // to your computer or laptop using USB port
  Serial.begin(115200);

  Serial.println();
  Serial.println();
  Serial.println();

  for (uint8_t t = 4; t > 0; t--) {
    Serial.printf("[SETUP] WAIT %d...\n", t);
    Serial.flush();
    delay(1000);
  }

  // Initiate Wi-Fi connection setup
  WiFi.begin(ssid, password);

  // Show status on serial monitor
  Serial.print("Connecting to ");
  Serial.print(ssid); Serial.println(" ...");

  // Wait for Wi-Fi connection and show progress on serial monitor
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected! IP address: ");
  Serial.println(WiFi.localIP());

  // Configure BME280 Sensor

  Serial.println("Checking BME280");
  unsigned status;

  status = bme.begin(I2C_ADDR);

  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
    Serial.print("SensorID was: 0x"); Serial.println(bme.sensorID(), 16);
    Serial.print("        ID of 0xFF probably means a bad address\n");
    while (1) delay(10); //***program will hang here if no valid sensor attached***
  } else {
    Serial.println("BME280 Detected");
  }
}

// This is the main section and will loop continuosly
void loop() {


  String postData;

  // This is the minimum amount of time to wait before
  // reading the sensor
  delay(DELAYTIME);

  // Read the sensor and set variables
  float tempC = bme.readTemperature();
  float humi = bme.readHumidity();
  float pressure = bme.readPressure() / 100.0F;


  // Print the values to the serial monitor for debug and info
  Serial.println('\n');
  Serial.print(humi, 1);
  Serial.print("\t\t");
  Serial.print(tempC, 1);
  Serial.print("\t\t");
  Serial.println(pressure, 1);


  // Build a string with data to send to JEDI. The format is
  // {
  //    "context": {
  //        "target_id" : "Sensor1"
  //    },
  //    "data": {
  //        "metric1" : metric_value,
  //        "metric2" : metric_value
  //    }
  // }
  //
  // Replace metric1 with what ever data metrics that you are
  // sending to JEDI. Replace metric_value with the value of
  // the metric. If you have more than one sensor, set the
  // target_id with the name of the sensor.

  postData = "{\"context\":{\"target_id\":\"BMESensorNode1\"}, \"data\":{\"tempC\":" + String(tempC) + ", " +
             "\"humi\":" + String(humi) + ", " +
             "\"pressure\":" + String(pressure) +
             " }}";

  if (WiFi.status() == WL_CONNECTED) {

    WiFiClient client;
    HTTPClient http;

    // Send the data to JEDI using HTTP.
    String address = String("http://") + String(host) + String("/v1/data/mc");
    http.begin(client, address);
    http.addHeader("Content-Type", "application/json");
    int httpCode = http.POST(postData);

    // httpCode will be negative on error
    if (httpCode > 0) {
      // HTTP header has been send and Server response header has been handled
      Serial.printf("[HTTP] POST... code: %d\n", httpCode);

      // file found at server
      if (httpCode == HTTP_CODE_OK) {
        const String& payload = http.getString();
        Serial.print("received payload:  ");
        Serial.println(payload);
      }
    } else {
      Serial.printf("[HTTP] POST... failed, error: %s\n", http.errorToString(httpCode).c_str());
    }

    http.end();  //Close connection

    // Blink the status LED
    digitalWrite(LED_BUILTIN, LOW);
    delay(500);
    digitalWrite(LED_BUILTIN, HIGH);

  } else {
    Serial.println("Error in WiFi connection");
  }


  // Wait for 5 seconds before repeating the loop
  delay(5000);
}
