Hi Guys, it sounds lazy, but it is not. I have tried many different possible codes, but I cannot make a led turn on or turn off, after my broke send a message. I have an esp8266 where it works fine.
My esp code is:
// Base ESP8266
#include <ESP8266WiFi.h>
WiFiClient WIFI_CLIENT;
// MQTT
#include <PubSubClient.h>
PubSubClient MQTT_CLIENT;
#define HEATER 14 //d5
// This function runs once on startup
void setup() {
// Initialize the serial port
Serial.begin(115200);
// Configure HEATER pin as an output
pinMode(HEATER, OUTPUT);
// Attempt to connect to a specific access point
WiFi.begin("xxxx", "yyyy");
// Keep checking the connection status until it is connected
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
// Print the IP address of your module
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
// This function handles received messages
void myMessageArrived(char* topic, byte* payload, unsigned int length) {
// Convert the message payload from bytes to a string
String message = "";
for (unsigned int i=0; i< length; i++) {
message = message + (char)payload[i];
}
// Print the message to the serial port
Serial.println(message);
// Check if message is "turn HEATER on"
if(message == "turn heater on") {
// Turn the HEATER on
digitalWrite(HEATER, HIGH);
}
// Check if message is "turn HEATER off"
if(message == "turn heater off") {
// Turn the HEATER off
digitalWrite(HEATER, LOW);
}
}
// This function connects to the MQTT broker
void reconnect() {
// Set our MQTT broker address and port
MQTT_CLIENT.setServer("192.168.0.200", 1883);
//MQTT_CLIENT.setServer("iot.eclipse.org", 1883);
MQTT_CLIENT.setClient(WIFI_CLIENT);
// Loop until we're reconnected
while (!MQTT_CLIENT.connected()) {
// Attempt to connect
Serial.println("Attempt to connect to MQTT broker");
MQTT_CLIENT.connect("esp_heater");
// Wait some time to space out connection requests
delay(3000);
}
Serial.println("MQTT connected");
// Subscribe to the topic where our web page is publishing messages
MQTT_CLIENT.subscribe("heater"); ///*****topic******//
// Set the message received callback
MQTT_CLIENT.setCallback(myMessageArrived);
}
// This function runs over and over again in a continuous loop
void loop() {
// Check if we're connected to the MQTT broker
if (!MQTT_CLIENT.connected()) {
// If we're not, attempt to reconnect
reconnect();
}
// Check for incoming MQTT messages
MQTT_CLIENT.loop();
}
What I am trying is
#include "application.h"
#include "MQTT.h"
void callback(char* topic, byte* payload, unsigned int length);
MQTT client("192.198.0.200", 1883, callback);
// This function handles received messages
void callback(char* topic, byte* payload, unsigned int length) {
// Convert the message payload from bytes to a string
String message = "";
for (unsigned int i=0; i< length; i++) {
message = message + (char)payload[i];
}
// Print the message to the serial port
Serial.println(message);
// Check if message is "turn HEATER on"
if(message == "turn heater on") {
// Turn the HEATER on
digitalWrite(HEATER, HIGH);
}
// Check if message is "turn HEATER off"
if(message == "turn heater off") {
// Turn the HEATER off
digitalWrite(HEATER, LOW);
}
}
void setup() {
// connect to the server(unique id by Time.now())
client.connect("sparkclient_" + String(Time.now()));
// publish/subscribe
if (client.isConnected()) {
client.subscribe("heater");
}
}
void loop() {
if (client.isConnected())
client.loop();
}
Your broker IP looks wrong.
Double checking your code would be the first step
Not sure why you are doing this tho'
You should be able to just write String message((const char*)payload, length);.
However, we strongly advise against the use of String for long running projects and variable string lengths due to the risk of heap fragmentation.
Without String you could write your handler like this
void callback(char* topic, byte* payload, unsigned int length) {
Serial.write(payload, length);
Serial.println();
// check message for known commands
if (strcmp(payload, "turn heater on") == 0) {
digitalWrite(HEATER, HIGH); // Turn the HEATER on
}
else if(strcmp(payload, "turn heater off") == 0) {
digitalWrite(HEATER, LOW); // Turn the HEATER off
}
}
BTW, commenting the obvious and dragging out code length with superfluous blank lines doesn't really help making your code more readable.
In loop() you are checking for client.isConnected() but you are not doing anything in case it isn't. Should you not try to reconnect?
Also you don't seem to check whether your connection ever gets established in setup() either.
That would be the first step in order to
I'm also no fan of using an IP address as string host name string (although it should work - it's just not very clean).
Try this instead
And you are not setting the pinMode() for your HEATER pin.
And one mess-up from my side - it should actually be strncmp() like this
if (strncmp((const char*)payload, "turn heater on", length) == 0) {
digitalWrite(HEATER, HIGH); // Turn the HEATER on
}
else if (strncmp((const char*)payload, "turn heater off", length) == 0) {
digitalWrite(HEATER, LOW); // Turn the HEATER off
}
BTW, wouldn't it be better to keep the client ID the same instead of making dynamic by adding the time to it?
If you keep the ID constant the broker can deliver queued messages when the same client comes back online.
You can try this
With that you can cycle through publishing an OFF, ON or wrong event to your broker by pressing the SETUP button and the D7 LED will reflect whether your ON or OFF was received.
Instead of hardcoding the comparisons against each possible command, I've created an array of commands which is traversed in order to find a match and then the respective index is used to trigger the respective action.
Hi @ScruffR ,
That was very nice from you reviewing so many times my bad code, but I am very happy it is working now, and your tips are gold. Thanks a million.