greenhousino/esp-receiver/src/main.cpp

304 lines
7.3 KiB
C++

#include <Arduino.h>
#include <RH_ASK.h>
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include "WiFiManager.h" //https://github.com/tzapu/WiFiManager
#include <PubSubClient.h> //MQTT
#include <ArduinoJson.h>
/**
* Baud Rate for the 433 Mhz connection.
* Caution: Must be the same for sender & receiver!
**/
#define RH_SPEED 2000
/**
* Pin for the receiver
**/
#if defined(USE_ARDUINO)
#define RH_RX_PIN 11
#elif defined(USE_ESPRESSIF)
#define RH_RX_PIN D8
#endif
#define RH_BUF_LEN 11
uint8_t rh_buf[RH_BUF_LEN];
#define RH_ASK_MAX_MESSAGE_LEN RH_BUF_LEN
const int AirValue = 800; //replace the value with value when placed in air
const int WaterValue = 345; //replace the value with value when placed in water
volatile boolean new_value = false;
const char *MQTT_BROKER = "192.168.178.74";
const char *MQTT_SENSOR_TOPIC = "living/sensor2";
const char *MQTT_CLIENT_ID = "living_mobile_sensor";
ESP8266WebServer server(80);
WiFiClient espClient;
PubSubClient mqttClient(MQTT_BROKER, 1883, espClient);
RH_ASK driver(RH_SPEED, RH_RX_PIN);
/**
* Message identifier constants:
* */
#define MSG_START 0x00
#define MSG_BAT 0x03
#define MSG_HEADER 0x05
#define MSG_ERR 0xee
char buff[20];
float Temperature = 0;
float Humidity = 0;
int soil = 0;
float SoilHumidity = 0;
long battery = 0;
long lastMillis = 0;
void handleRoot(); // function prototypes for HTTP handlers
void handleNotFound();
void reconnect();
String SendHTML();
void publishData(float temp, float humid, float soil, long battery);
void callback(char *inTopic, byte *payload, unsigned int length);
void configModeCallback(WiFiManager *myWiFiManager)
{
Serial.println("Entered config mode");
Serial.println(WiFi.softAPIP());
//if you used auto generated SSID, print it
Serial.println(myWiFiManager->getConfigPortalSSID());
}
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
if (!driver.init())
{
Serial.println("init failed");
}
else
{
Serial.println("init done");
}
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifiManager;
//reset settings - for testing
//wifiManager.resetSettings();
//set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
wifiManager.setAPCallback(configModeCallback);
//fetches ssid and pass and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP"
//and goes into a blocking loop awaiting configuration
if (!wifiManager.autoConnect())
{
Serial.println("failed to connect and hit timeout");
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(1000);
}
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
mqttClient.setCallback(callback);
server.on("/", handleRoot);
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
// switch build in led OFF (with HIGH);
digitalWrite(LED_BUILTIN, HIGH);
}
void loop()
{
uint8_t len = sizeof(rh_buf);
long ms = millis();
if (driver.recv(rh_buf, &len))
{
Serial.println("Message received.");
switch (rh_buf[0])
{
case MSG_START:
// start message
Serial.println("0x00 start byte");
break;
case MSG_HEADER:
// DHT Temperature
digitalWrite(LED_BUILTIN, LOW);
Serial.println("DHT Temp");
memcpy(&Temperature, &rh_buf[1], 4);
Serial.print(Temperature);
Serial.println(" °C");
// DHT Humidity:
Serial.println("DHT Humidity");
memcpy(&Humidity, &rh_buf[5], 4);
Serial.print(Humidity);
Serial.println(" %");
Serial.println("Soil Humidity");
memcpy(&soil, &rh_buf[9], 2);
Serial.println(soil);
SoilHumidity = (float)(map(soil, AirValue, WaterValue, 0, 100));
Serial.println(SoilHumidity);
new_value = true;
break;
case MSG_BAT:
// battery data
digitalWrite(LED_BUILTIN, LOW);
Serial.println("Battery");
memcpy(&battery, &rh_buf[1], 4);
Serial.print(battery);
Serial.println(" mV");
new_value = true;
break;
case MSG_ERR:
// error
Serial.println("0xEE error");
break;
default:
// should never happen
break;
}
}
server.handleClient();
if (!mqttClient.connected())
{
reconnect();
}
if (ms - lastMillis > 5000 && new_value)
{
publishData(Temperature, Humidity, SoilHumidity, battery);
lastMillis = ms;
new_value = false;
}
mqttClient.loop();
digitalWrite(LED_BUILTIN, HIGH);
}
void reconnect()
{
// Loop until we're reconnected
while (!mqttClient.connected())
{
Serial.println("INFO: Attempting MQTT connection...");
// Attempt to connect
if (mqttClient.connect(MQTT_CLIENT_ID))
{
Serial.println("INFO: connected");
}
else
{
Serial.print("ERROR: failed, rc=");
Serial.print(mqttClient.state());
Serial.println("DEBUG: try again in 5 seconds");
// Wait 5 seconds before retrying
//delay(5000);
return;
}
}
}
void callback(char *inTopic, byte *payload, unsigned int length)
{
Serial.println("Got RF data");
Serial.write(payload, length);
Serial.println();
// convert the byte non terminated payload to string:
char pltext[length + 1];
strncpy(pltext, (char *)payload, length);
pltext[length] = '\0';
// convert payload string to int:
int num = atoi(pltext);
Serial.println(pltext);
Serial.println("RF data sent");
}
void handleRoot()
{
server.send(200, "text/html", SendHTML());
}
void handleNotFound()
{
server.send(404, "text/plain", "Not found");
}
// function called to publish the temperature and the humidity
void publishData(float temp, float humid, float soil, long battery)
{
// create a JSON object
// doc : https://github.com/bblanchon/ArduinoJson/wiki/API%20Reference
DynamicJsonDocument doc(1024);
doc["temperature"] = (String)temp;
doc["humidity"] = (String)humid;
doc["soilhumidity"] = (String)soil;
doc["battery"] = (String)battery;
serializeJson(doc, Serial);
Serial.println("");
char data[200];
serializeJson(doc, data);
mqttClient.publish(MQTT_SENSOR_TOPIC, data, true);
yield();
}
String SendHTML()
{
String ptr = "<!DOCTYPE html> <html>\n";
ptr += "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr += "<title>Wiesendamm Wetter Report</title>\n";
ptr += "<meta http-equiv=\"refresh\" content=\"2\" >";
ptr += "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
ptr += "body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
ptr += "p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
ptr += "</style>\n";
ptr += "</head>\n";
ptr += "<body>\n";
ptr += "<div id=\"webpage\">\n";
ptr += "<h1>Wiesendamm Wetter Report</h1>\n";
ptr += "<p>Temperature: ";
ptr += (float)Temperature;
ptr += " C</p>";
ptr += "<p>Humidity: ";
ptr += (float)Humidity;
ptr += " %</p>";
ptr += "<p>Soil Humidity: ";
ptr += (float)SoilHumidity;
ptr += " %</p>";
ptr += "<p>Battery: ";
ptr += (float)battery;
ptr += " mV</p>";
ptr += "</div>\n";
ptr += "</body>\n";
ptr += "</html>\n";
return ptr;
}