Room Sensor Issues (mqtt)

Hi All,

First time posting, Is there anyone who can help me out with the following code? I've tried it multiple ways but cannot get the target output.

Objective:
Readings taken from three sensors (DHT22: Temp & Humidity/Soil capacitance sensor) and result output over mqtt to a local server

Issues:
I've tried running the script a few different ways and get various different results i.e. only one reading being output over mqtt and the others not sending. I think this is simply down to the way the loop is running but need some help.

Code:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

#define wifi_ssid "nope"
#define wifi_password "nope"

#define mqtt_server "nope"
#define mqtt_user "nope"
#define mqtt_password "nope"

#define soilmoisture_topic "sensor/test/moisture/plant/test"
#define soilstate_topic "sensor/test/state/plant/test"
#define humidity_topic "sensor/test/test/humidity"
#define temperature_topic "sensor/test/test/temperature"

#define DHTTYPE DHT22
#define DHTPIN  D2

WiFiClient test;
PubSubClient client(test);
DHT dht(DHTPIN, DHTTYPE); // 11 works fine for ESP8266



void setup() {
  Serial.begin(115200); // open serial port, set the baud rate to 9600 bps
  dht.begin();
  setup_wifi();
  client.setServer(mqtt_server, 1883);
}

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(wifi_ssid);

  WiFi.begin(wifi_ssid, wifi_password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    // If you do not want to use a username and password, change next line to
    // if (client.connect("ESP8266Client")) {
    if (client.connect("ESP8266Client", mqtt_user, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

long lastMsg = 0;
float temp = 0.0;
float hum = 0.0;
float diff = 1.0;
float moist = 0.0;

const int AirValue = 713;   //you need to replace this value with Value_1
const int WaterValue = 276;  //you need to replace this value with Value_2
int intervals = (AirValue - WaterValue) / 3;
int soilMoistureValue = 0;

void loop() {
  long now = millis();
  if (now - lastMsg > 60000) {
    lastMsg = now;
    if (!client.connected()) {
      reconnect();
    }
    client.loop();
    Serial.println("Starting sensor readings");

    float newTemp = dht.readTemperature(); {

      int soilMoistureValue = analogRead(A0);  //put Sensor insert into soil

      temp = newTemp;
      Serial.print("New temperature:");
      Serial.println(String(temp).c_str());
      client.publish(temperature_topic, String(temp).c_str(), true);
    }


    float newHum = dht.readHumidity(); {
      hum = newHum;
      Serial.print("New humidity:");
      Serial.println(String(hum).c_str());
      client.publish(humidity_topic, String(hum).c_str(), true);
    }


    int soilMoistureValue = analogRead(A0);
    if (soilMoistureValue > WaterValue && soilMoistureValue < (WaterValue + intervals))
    {
      Serial.println(soilMoistureValue);
      Serial.println("Very Wet");
      delay(1000);
      client.publish(soilmoisture_topic, String(soilMoistureValue).c_str(), true);
      delay(1000);
      client.publish(soilstate_topic, String("Very Wet").c_str(), true);

    }
    else if (soilMoistureValue > (WaterValue + intervals) && soilMoistureValue < (AirValue - intervals))
    {
      Serial.println(soilMoistureValue);
      Serial.println("Wet");
      delay(1000);
      client.publish(soilmoisture_topic, String(soilMoistureValue).c_str(), true);
      delay(1000);
      client.publish(soilstate_topic, String("Wet").c_str(), true);
    }
    else if (soilMoistureValue < AirValue && soilMoistureValue > (AirValue - intervals))
    {
      Serial.println(soilMoistureValue);
      Serial.println("Dry");
      delay(1000);
      client.publish(soilmoisture_topic, String(soilMoistureValue).c_str(), true);
      delay(1000);
      client.publish(soilstate_topic, String("Dry").c_str(), true);
    }
    client.publish(soilmoisture_topic, String(soilMoistureValue).c_str(), true);
    delay(1000);
    Serial.println("Finished sensor readings");
  }
}/code]
      Serial.println(String(temp).c_str());

WTF? The println() method is perfectly capable of printing a float without your ham-fisted "help".

    float newTemp = dht.readTemperature(); {

      int soilMoistureValue = analogRead(A0);  //put Sensor insert into soil

      temp = newTemp;
      Serial.print("New temperature:");
      Serial.println(String(temp).c_str());
      client.publish(temperature_topic, String(temp).c_str(), true);
    }

What are the curly braces for? Why are you reading the soil moisture sensor in that block?

    if (soilMoistureValue > WaterValue && soilMoistureValue < (WaterValue + intervals))

Plus intervals?

Why are you publishing the soil moisture value more than once? Do you REALLY need to publish the soil state? It seems reasonable that the server could determine the state from the value.

only one reading being output over mqtt and the others not sending.

But you are not going to tell us which one? Well, fine. Be that way.

You have global variables for your parameters but you read them into new values and then immediately assign them to the globals. Just assign it directly. Also, there is a lot of duplicated code in your if() else() structure.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

#define wifi_ssid "nope"
#define wifi_password "nope"

#define mqtt_server "nope"
#define mqtt_user "nope"
#define mqtt_password "nope"

#define soilmoisture_topic "sensor/test/moisture/plant/test"
#define soilstate_topic "sensor/test/state/plant/test"
#define humidity_topic "sensor/test/test/humidity"
#define temperature_topic "sensor/test/test/temperature"

#define DHTTYPE DHT22
#define DHTPIN  D2

WiFiClient test;
PubSubClient client(test);
DHT dht(DHTPIN, DHTTYPE); // 11 works fine for ESP8266

void setup() {
  Serial.begin(115200); // open serial port, set the baud rate to 9600 bps
  dht.begin();
  setup_wifi();
  client.setServer(mqtt_server, 1883);
}

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(wifi_ssid);

  WiFi.begin(wifi_ssid, wifi_password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    // If you do not want to use a username and password, change next line to
    // if (client.connect("ESP8266Client")) {
    if (client.connect("ESP8266Client", mqtt_user, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

unsigned long lastMsg = 0;
float temp = 0.0;
float hum = 0.0;
float diff = 1.0;
float moist = 0.0;

const int AirValue = 713;   //you need to replace this value with Value_1
const int WaterValue = 276;  //you need to replace this value with Value_2
const int intervals = (AirValue - WaterValue) / 3;
unsigned int soilMoistureValue;

void loop() {
  unsigned long now = millis();
  if (now - lastMsg > 60000) {
    lastMsg = now;
    if (!client.connected()) {
      reconnect();
    }
    client.loop();
    Serial.println("Starting sensor readings");

    temp = dht.readTemperature();
    Serial.print("New temperature:");
    Serial.println(temp, 4);
    client.publish(temperature_topic, String(temp).c_str(), true);

    hum = dht.readHumidity();
    Serial.print("New humidity:");
    Serial.println(hum, 4);
    client.publish(humidity_topic, String(hum).c_str(), true);

    soilMoistureValue = analogRead(A0);
    Serial.print("New soil moisture value:");
    Serial.println(soilMoistureValue);
    char *soilState = "unknown";
    if (soilMoistureValue >= WaterValue && soilMoistureValue < (WaterValue + intervals))
    {
      soilState = "Very Wet";
    }
    else if (soilMoistureValue >= (WaterValue + intervals) && soilMoistureValue < (AirValue - intervals))
    {
      soilState = "Wet";
    }
    else if (soilMoistureValue < AirValue && soilMoistureValue >= (AirValue - intervals))
    {
      soilState = "Dry";
    }
    Serial.print("New soil state:");
    Serial.println(soilState);
    delay(1000);
    char strValue[5];
    sprintf( strValue, "%u", soilMostureValue );
    client.publish(soilmoisture_topic, strValue, true);
    delay(1000);
    client.publish(soilstate_topic, soilState, true);
    delay(1000);
    Serial.println("Finished sensor readings");
  }
}

Finally, your testing for soil state needs to be inclusive ( less than or greater-than-or-equal ) or you will miss the cases where the soilValue equals one of boundaries. I have fixed that. The other problem is what happens when the soilValue is very low (less than WaterValue ) or very high ( greater than AirValue). Those two reasons are why your code occasionally didn't spit out anything. The current code will at least tell you "unknown"

First, Can I just say thank you to both of you for your replies.

PaulS, Can I start by apologising for this very poor and absurd coding I have presented you. It originally started out as two working pieces of code that I have tried to join together, albeit in a very bad way, I moved and added so much of the original code in a desperate attempt to get the desired outcome and when I couldn't get this I turned here for help. I thought I had taken out the garbage I had inserted but clearly I didn't do a very good job of that either.

With regards to the soil state being published, this was originally what I wanted to receive and added the moisture value at a later date in my effort to understand what was going wrong. I totally agree that this is something the server is more than capable of dealing with on its end.

blh64, I have copied your code and I can now see the temperature and humidity being published to my server. Unfortunately I am still not getting any published readings from the soil sensor as can be seen in the attached screenshot.

I don't know that much about mqtt, but your screenshot looks like you are only subscribed to temperature and humidity so those are the only messages you are seeing. I would have expected you to subscribe to
"sensor/test/moisture/plant/test" and "sensor/test/state/plant/test"

So the program you see in the screenshot is MQTT.fx and what that is doing is scanning all topics currently being published to my server.

I’ve cleared out all the other topics (a lot of others) and subscribed to the temperature and humidity topics which are the ones your seeing up the top. But I’m not getting any of the plant topics being published which is where I am confused

Can MQTT.fx subscribe to "sensor/test/#" so it get anything sent to sensor/test
You should also put client.loop(); so it gets called every pass of loop instead of just when sensor reading are to be sent.