// #include // Wi-Fi #include // #include // MQTT library #include // JSON library #include const char* ssid = "DEV-NULL"; const char* password = "########"; // MQTT Setup Start #define mqtt_server "10.0.0.10" WiFiClient wifiClient; // do the WiFi instantiation thing PubSubClient MQTTclient( mqtt_server, 1883, wifiClient ); //do the MQTT instantiation thing // Define MQTT variables #define mqtt_topic_Temp "weather_station_1/Temp" #define mqtt_topic_TempC "weather_station_1/TempC" // Comnpensated #define mqtt_topic_Humidity "weather_station_1/Humidity" #define mqtt_topic_HumidityC "weather_station_1/HumidityC" // Comnpensated #define mqtt_topic_Pressure "weather_station_1/Pressure" #define mqtt_topic_Altitude "weather_station_1/Altitude" #define mqtt_topic_Dewpoint "weather_station_1/Dewpoint" #define mqtt_topic_Light "weather_station_1/Light" #define mqtt_topic_eCO2 "weather_station_1/eCO2" #define mqtt_topic_TVOC "weather_station_1/TVOC" #define mqtt_topic_AQI "weather_station_1/AQI" #define mqtt_topic_windSpeed "weather_station_1/windSpeed" #define mqtt_topic_windDirection "weather_station_1/windDirection" #define mqtt_topic_Rainfall "weather_station_1/Rainfall" #define mqtt_topic_WindChill "weather_station_1/WindChill" #define mqtt_topic_HeatIndex "weather_station_1/HeatIndex" #define mqtt_topic_TestVar "weather_station_1/TestVar" #define mqtt_topic_json "weather_station_1/json" #define mqtt_topic_json2 "weather_station_2/json" //MQTT Setup End // Below are the pin definitions for each sensor of the weather meter kit // Pins for Weather Carrier with ESP32 Processor Board int windDirectionPin = 35; int windSpeedPin = 14; int rainfallPin = 27; // Create an instance of the weather meter kit SFEWeatherMeterKit weatherMeterKit(windDirectionPin, windSpeedPin, rainfallPin); ////////////////////////// // Sparkfun ENS160 Sensor #include SparkFun_ENS160 ens; int ensStatus; // Sparkfun BME280 Sensor #include BME280 bme; // Define PIN for Light photo-resister to monitor const byte lightPin = 34; // Set up core variables float Temp, TempC, Humidity, HumidityC, Pressure, Altitude, Dewpoint, Light, eCO2, TVOC, AQI, windSpeed, windDirection, Rainfall, WindChill, HeatIndex, TestVar; void setup() { Wire.begin(); // Prepare the serial port. Serial.begin(115200); Serial.println("Serial connection established."); // Stop Bluetooth to save power Serial.println("Stopping Bluetooth"); btStop(); // Begin Wifi connect Serial.println("Running with Serial active..."); Serial.print("Connecting to "); Serial.println(ssid); WiFi.mode(WIFI_STA); WiFi.disconnect(); delay(2000); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); //end Wifi connect // Set up the MQTT client / server MQTTclient.setServer(mqtt_server, 1883); MQTTclient.setCallback(callback); // Sparkfun BME Start if (bme.beginI2C() == false) //Begin communication over I2C { Serial.println("The BME sensor did not respond. Please check wiring."); while (1) ; //Freeze } // Sparkfun ENS Start if (!ens.begin()) { Serial.println("The ENS sensor did not respond. Please check wiring."); while (1); } // Reset the indoor air quality sensor's settings. if (ens.setOperatingMode(SFE_ENS160_RESET)) Serial.println("ENS160 Indoor air quality sensor reset; Ready."); Serial.println(" "); delay(100); // Device needs to be set to idle to apply any settings. // myENS.setOperatingMode(SFE_ENS160_IDLE); // Set to standard operation // Others include SFE_ENS160_DEEP_SLEEP and SFE_ENS160_IDLE ens.setOperatingMode(SFE_ENS160_STANDARD); // There are four values here: // 0 - Operating ok: Standard Operation // 1 - Warm-up: occurs for 3 minutes after power-on. // 2 - Initial Start-up: Occurs for the first hour of operation. // and only once in sensor's lifetime. // 3 - No Valid Output ensStatus = ens.getFlags(); Serial.print("Gas Sensor Status Flag: "); Serial.println(ensStatus); // Setup the Sparkfun weather kit #ifdef SFE_WMK_PLAFTORM_UNKNOWN // The platform you're using hasn't been added to the library, so the // expected ADC values have been calculated assuming a 10k pullup resistor // and a perfectly linear 16-bit ADC. Your ADC likely has a different // resolution, so you'll need to specify it here: weatherMeterKit.setADCResolutionBits(10); Serial.println(F("Unknown platform! Please edit the code with your ADC resolution!")); Serial.println(); #endif // Begin weather meter kit weatherMeterKit.begin(); Serial.println(" "); Serial.println("=============================="); Serial.println("Setup Complete....."); Serial.println("=============================="); Serial.println(" "); delay(1000); } // This allows the MQTT broker to send info back, I believe void callback(char* topic, byte* payload, unsigned int length) { } // Function to calculate Heat Index float calculateHeatIndex(float T, float RH) { // Constants from NOAA's formula float c1 = -42.379, c2 = 2.04901523, c3 = 10.14333127, c4 = -0.22475541; float c5 = -0.00683783, c6 = -0.05481717, c7 = 0.00122874, c8 = 0.00085282, c9 = -0.00000199; float HI = c1 + c2 * T + c3 * RH + c4 * T * RH + c5 * T * T + c6 * RH * RH + c7 * T * T * RH + c8 * T * RH * RH + c9 * T * T * RH * RH; // Adjustment for lower ranges of temperature/humidity if (RH < 13 && (T >= 80.0 && T <= 112.0)) { HI -= ((13 - RH) / 4) * sqrt((17 - abs(T - 95.0)) / 17); } else if (RH > 85 && (T >= 80.0 && T <= 87.0)) { HI += ((RH - 85) / 10) * ((87 - T) / 5); } return HI; } // Function to calculate Wind Chill float calculateWindChill(float T, float V) { return 35.74 + 0.6215 * T - 35.75 * pow(V, 0.16) + 0.4275 * T * pow(V, 0.16); } void reconnect() { // Loop until we're reconnected int counter = 0; while (!MQTTclient.connected()) { if (counter==5){ ESP.restart(); } counter+=1; Serial.print("Attempting MQTT connection..."); // Attempt to connect if (MQTTclient.connect("weather_station_1")) { Serial.println("connected"); } else { Serial.print("failed, rc="); Serial.print(MQTTclient.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void getValues() { Temp = bme.readTempF(); // (reads in C) C * 9/5 + 32 to convert to "F" Humidity = bme.readFloatHumidity(); ens.setTempCompensationCelsius(Temp); ens.setRHCompensationFloat(Humidity); TempC = ens.getTempCelsius(); HumidityC = ens.getRH(); Pressure = (bme.readFloatPressure() / 100.0F); // standard at sea level is 1,013.25 hPa. Altitude = bme.readFloatAltitudeFeet(); // in feet Dewpoint = bme.dewPointF(); Light = analogRead(lightPin); // 0 <--> 4095 (12 bit resolution) eCO2 = ens.getECO2(); // CO2 concentration (eCO2) TVOC = ens.getTVOC(); // Total Volatile Organic Compounds (ppb) AQI = ens.getAQI(); windSpeed = (weatherMeterKit.getWindSpeed()*0.621371); // convert to mph windDirection = weatherMeterKit.getWindDirection(); Rainfall = (weatherMeterKit.getTotalRainfall()*0.0393700787); // convert from mm to in of rainfall HeatIndex = calculateHeatIndex(TempC, HumidityC); WindChill = calculateWindChill(TempC, windSpeed); } void pushValues() { // Push individual topics to the MQTT broker MQTTclient.publish(mqtt_topic_Temp, String(Temp).c_str(),false); MQTTclient.publish(mqtt_topic_TempC, String(TempC).c_str(),false); MQTTclient.publish(mqtt_topic_Humidity, String(Humidity).c_str(),false); MQTTclient.publish(mqtt_topic_HumidityC, String(HumidityC).c_str(),false); MQTTclient.publish(mqtt_topic_Pressure, String(Pressure).c_str(),false); MQTTclient.publish(mqtt_topic_Altitude, String(Altitude).c_str(),false); MQTTclient.publish(mqtt_topic_Dewpoint, String(Dewpoint).c_str(),false); MQTTclient.publish(mqtt_topic_Light, String(Light).c_str(),false); MQTTclient.publish(mqtt_topic_eCO2, String(eCO2).c_str(),false); MQTTclient.publish(mqtt_topic_TVOC, String(TVOC).c_str(),false); MQTTclient.publish(mqtt_topic_AQI, String(AQI).c_str(),false); MQTTclient.publish(mqtt_topic_windSpeed, String(windSpeed).c_str(),false); MQTTclient.publish(mqtt_topic_windDirection, String(windSpeed).c_str(),false); MQTTclient.publish(mqtt_topic_Rainfall, String(Rainfall).c_str(),false); MQTTclient.publish(mqtt_topic_WindChill, String(WindChill).c_str(),false); MQTTclient.publish(mqtt_topic_HeatIndex, String(HeatIndex).c_str(),false); // Create JSON object StaticJsonDocument<3000> jsonDoc; jsonDoc["Temp"] = Temp; jsonDoc["TempC"] = TempC; jsonDoc["Humidity"] = Humidity; jsonDoc["HumidityC"] = HumidityC; jsonDoc["Pressure"] = Pressure; jsonDoc["Altitude"] = Altitude; jsonDoc["Dewpoint"] = Dewpoint; //jsonDoc["Light"] = Light; //jsonDoc["eCO2"] = eCO2; //jsonDoc["TVOC"] = TVOC; //jsonDoc["AQI"] = AQI; jsonDoc["windSpeed"] = windSpeed; jsonDoc["windDirection"] = windDirection; jsonDoc["Rainfall"] = Rainfall; jsonDoc["HeatIndex"] = HeatIndex; jsonDoc["WindChill"] = WindChill; // Serialize JSON object char jsonBuffer[3000]; serializeJson(jsonDoc, jsonBuffer); // Publish JSON data to MQTT MQTTclient.publish(mqtt_topic_json, jsonBuffer); } void printValues() { // Array of labels const char* labels[] = { "Temperature", \ "Temperature (Comp.)", \ "Humidity", \ "Humidity (Comp.)", \ "Pressure", \ "Altitude", \ "Dewpoint", \ "Light Reading", \ "CO2 Conc.", \ "Total VOCs", \ "Air Quality Index", \ "Wind Speed", \ "Wind Direction", \ "Rainfall", \ "WindChill", \ "HeatIndex", \ "TestVar" }; // Array of corresponding values float values[] = { Temp, \ TempC, \ Humidity, \ HumidityC, \ Pressure, \ Altitude, \ Dewpoint, \ Light, \ eCO2, \ TVOC, \ AQI, \ windSpeed, \ windDirection, \ Rainfall, \ WindChill, \ HeatIndex, \ TestVar }; // Array of units const char* units[] = { "°F", \ "°F", \ "%", \ "%", \ "hPa", \ "feet", \ "°F", \ "(0-4096)", \ "ppm", \ "ppb", \ "aqi", \ "mph", \ "degrees", \ "in", \ "°F", \ "°F", \ "#" }; // AQI // https://www.airnow.gov/aqi/aqi-basics/ // 1: "Excellent" // 2: "Good" // 3: "Moderate" // 4: "Poor" // 5: "Unhealthy" const int dataCount = sizeof(values) / sizeof(values[0]); // Calculate array size // Spacer Serial.println(" "); // Print formatted column of results by combining the three arrays. for (int i = 0; i < dataCount; i++) { char buffer[50]; // Temporary buffer for formatted string sprintf(buffer, "%-20s: %-8.2f %s", labels[i], values[i], units[i]); Serial.println(buffer); } } void loop() { // Keep connected to MQTT if (!MQTTclient.connected()){ reconnect(); } // Read sensor values getValues(); // Push to MQTT Broker pushValues(); // Print values to serial printValues(); delay(4000); }