// WireWrapper - Version: Latest 

// WireData - Version: Latest 

/*

  Funziona con: Uno WiFi Rev.2 board + BME280 (connessa ad SCL, SCA) + Un sensore analogico (connesso ad A0)
  facilmente estendibile per avere fino a 4 sensori analogici

*/

#include <PubSubClient.h>
#include <WiFiNINA.h> // for MKR1000 change to: #include <WiFi101.h>
#include <avr/wdt.h>
//#include <Wire.h>
#include <WireWrapper.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define SEALEVELPRESSURE_HPA (1011.0)
#define BSZ 350
#define INTERVAL 5000
#define WCLOCK 100
#define DELTAP 26.11
#define CORRECT 2.95

#define DESCRIPTION_REQ "to/all"
#define SOURCE_TOPIC "from/test/bme1/gpio"
//#define SOURCE_TOPIC "from/demo/bme1/gpio"  // topic su cui pubblica i dati

#define WDTO_16S 15

///////please enter your sensitive data in the Secret tab/arduino_secrets.h
//char ssid[] = "PocketCube-ECCB";        // your network SSID (name)
//char pass[] = "1MAD00DH";    // your network password (use for WPA, or use as key for WEP)

char ssid[] = "WebCube4-M3T5";        // il nome dela tua rete SSID (name)
char pass[] = "LJ68YQ46";    // passwd di accesso (use for WPA, or use as key for WEP)
const char clientID[] = "wheter1";
const char mqttUser[] = "pissir";
const char mqttPassword[] = "pissir2020";

// To connect with SSL/TLS:
// 1) Change WiFiClient to WiFiSSLClient.
// 2) Change port value from 1883 to 8883.
// 3) Change broker value to a server with a known SSL/TLS root certificate 
//    flashed in the WiFi module.


WiFiClient wifiClient;
PubSubClient client(wifiClient);

// Indirizzo del Message Broker MQTT (quello che segue รจ quello del Piemonte Orientale)
IPAddress server(192, 168, 20, 67);

// struttura del messaggio JSON che viene pubblicato
char const description[]="{\"test/bme1/gpio\":[\n{\"name\":\"TM\",\"type\":\"analogin\"},\n{\"name\":\"P0\",\"type\":\"analogin\"},\n{\"name\":\"P1\",\"type\":\"analogin\"},\n{\"name\":\"HU\",\"type\":\"analogin\"},\n{\"name\":\"CO\",\"type\":\"analogin\"}\n]}";
//char const description[]="{\"demo/bme1/gpio\":[\n{\"name\":\"TM\",\"type\":\"analogin\"},\n{\"name\":\"P0\",\"type\":\"analogin\"},\n{\"name\":\"P1\",\"type\":\"analogin\"},\n{\"name\":\"HU\",\"type\":\"analogin\"},\n{\"name\":\"CO\",\"type\":\"analogin\"}\n]}";


const long interval = 10000;
unsigned long previousMillis = 0;
// define sensors on the 6 Analog inputs

int sensor[4] = {A0, A1, A2, A3};
Adafruit_BME280 bme;

int count = 0;
int myclock = 0;

void callback(char* topic, byte* payload, unsigned int length) {
  int val;
  int pin;
  if(strcmp(topic,DESCRIPTION_REQ)==0) {
    //Serial.println("Description Sent");
    client.publish(SOURCE_TOPIC "/description", description);
  }
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(clientID,mqttUser,mqttPassword)) {
      Serial.println("connected");
      // Once connected, publish an announcement...
     // client.publish(SOURCE_TOPIC,"I am Ready");
      // ... and resubscribe
      client.subscribe(DESCRIPTION_REQ);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}


void setup() {
  //Initialize serial and wait for port to open:
  delay(250);
  Serial.begin(9600);
  wdt_enable(WDTO_16S);
  // attempt to connect to Wifi network:
  Serial.print("Attempting to connect to WPA SSID: ");
  Serial.println(ssid);
  
  while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
  // failed, retry
    Serial.print(".");
    delay(5000);
  }

  Serial.println("You're connected to the network");
  Serial.println();

  client.setServer(server, 1883); // or local broker
  client.setCallback(callback);
  delay(1000);
  wdt_reset();
  //starts the BME280 probe
  bme.begin(0x76);


  // You can provide a unique client ID, if not set the library uses Arduin-millis()
  // Each client must have a unique client ID
  // client.setId(clientId);

  // You can provide a username and password for authentication
  // client.setUsernamePassword(mqttUser, mqttPassword);

  // set a will message, used by the broker when the connection dies unexpectantly
  // you must know the size of the message before hand, and it must be set before connecting


  Serial.println("You're connected to the MQTT broker!");
  Serial.println();

  wdt_enable(WDTO_2S);
}

void loop() {
  char message[BSZ];
  float val;

  uint32_t x=0;

  wdt_reset();
  if (!client.connected()) {
    reconnect();
  }
  wdt_reset();
  client.loop();
  
  if(myclock > INTERVAL) {
    //Serial.println("loop");
    switch(count) {
      case 0:
        val = bme.readTemperature();
        sprintf(message,"{\"event\":\"%d.%d\"}",(int)val, (int)(val*100)-(int)val*100);
        client.publish(SOURCE_TOPIC "/TM", message);
        break;

      case 1:
        val = bme.readPressure() / 100.0F + CORRECT;
        sprintf(message,"{\"event\":\"%d.%d\"}",(int)val, (int)(val*100)-(int)val*100);
        client.publish(SOURCE_TOPIC "/P0", message);
        break;
      case 2:
        val = bme.readPressure() / 100.0F + DELTAP+CORRECT;
        sprintf(message,"{\"event\":\"%d.%d\"}",(int)val, (int)(val*100)-(int)val*100);
        client.publish(SOURCE_TOPIC "/P1", message);
        break;
      case 3:
        val = bme.readHumidity();
        sprintf(message,"{\"event\":\"%d.%d\"}",(int)val, (int)(val*100)-(int)val*100);
        client.publish(SOURCE_TOPIC "/HU", message);
        break;
      case 4:
        x = analogRead(A0);
        sprintf(message,"{\"event\":\"%d.%d\"}",(int) x);
        client.publish(SOURCE_TOPIC "/CO", message);
    }
    count++;
    if(count>4) count = 0;
    myclock = 0;
  }
  delay(WCLOCK);
  myclock += WCLOCK;
}