Failing to connect to MQTT Broker

Hi all,

Ive setup my first MQTT server on an old Pi3.

I imaged the SD Card with a clean bullseye 32bit install and then followed this here guide to install MQTT without authentication.

I can connect to it from a separate PC using MQTT Explorer and also connect to it and publish and subscribe to a topic using my iPhone and EasyMQTT...

But for the life of me the below code below WILL NOT connect to the broker on my ESP module... the author of the code has checked my file and says if he loads it on his that it connects to his MQTT broker...

What could be causing mine to never connect???

#include <SoftwareSerial.h>
#include <PubSubClient.h>
#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiClient.h>
#include <ArduinoOTA.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include "helpers.h"
#include "global.h"

SoftwareSerial swSer;

WiFiClient espClient;

volatile long lastCharTime = 0;
volatile long lastMasterRx = 0;
volatile long lastHeadRx = 0;
int charCount = 0;
unsigned char charBuff[13];
unsigned char charBuffNew[13];

unsigned int checksum1 = 0;
unsigned int checksum2 = 0;
unsigned int lastChecksum = 0;

byte powerByte = 0;
byte fanByte = 0;
byte modeByte = 0;
byte tempByte = 0;
byte zoneByte = 0; 

long previousMillis = 0;       // will store last time loop ran
long interval = 5000;           // interval at which to limit loop
int i;

long previousMQTTCommand = 0;
int waitForCommand = 2000;
boolean changeWaiting = 0;
boolean justChanged = 0;

char id[5];

//MQTT
PubSubClient MQTTClient(espClient);
char subPath[] = {'h', 'a', '/', 'm', 'o', 'd', '/', 'F', 'F', 'F', 'F', '/', '#','\0'};


//*******************************
//      FUNCTIONS
void ConfigureWifi()
{
  Serial.println("Configuring Wifi");
  WiFi.begin (config.ssid.c_str(), config.password.c_str());
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
    Serial.println("");
    Serial.println("WiFi connected");

  if (!config.dhcp)
  {
    WiFi.config(IPAddress(config.IP[0],config.IP[1],config.IP[2],config.IP[3] ),  IPAddress(config.Gateway[0],config.Gateway[1],config.Gateway[2],config.Gateway[3] ) , IPAddress(config.Netmask[0],config.Netmask[1],config.Netmask[2],config.Netmask[3] ));
  }
 Serial.print("IP address: ");
 Serial.println(WiFi.localIP());
 Serial.print("Serial: ");
 Serial.println(ESP.getChipId());
 Serial.print("MQTT ID: ");
  
 unsigned long espChipId = ESP.getChipId();
 char b[7];
 sprintf(b, "%i", espChipId);
 for (int i=0;i<4;i++){
  id[i] = b[i+3];
 }
 Serial.println(id);
id['F','F','F','F','\0'];
 // Redefine the ID path
// for (int i=0;i<4;i++){
//   subPath[i+7] = id[i];
// }
}

void callback(char* topic, byte *payload,unsigned int length) 
{
  Serial.print("R: ");
	Serial.print(topic);
	Serial.print(" ");
  char messageBuffer[30];  //an array of chars to copy payload to
  memcpy(messageBuffer, payload, length);  //copy the payload
  messageBuffer[length] = '\0';  //turn it into a C string
  Serial.println(messageBuffer);  //print it
    // If there has been no MQTT message received for a bit
    // assume the data we have is stale and recompile the array
  
    if((millis() - previousMQTTCommand > waitForCommand) && (changeWaiting == 0)) {
      previousMQTTCommand = millis();
      //Copy the existing AC config bytes
      for (int i = 0; i < 13;i++){
        charBuffNew[i] = charBuff[i];
      }
    }
  
    if (topic[11] == '/' && topic[12] == 'X'){ 
      //its a command that needs to be sent to the BUS
      // modify the array with the right settings.
      
      if (topic[13] == 'Z'){
        changeWaiting = 1; // Flag for sensing there is a change to be sent to the BUS
        //Serial.println("Zones");
        if (payload[3] == '1'){
          bitWrite(charBuffNew[5],3, 1);
        }else{
          bitWrite(charBuffNew[5],3, 0);
        }
        if (payload[2] == '1'){
          bitWrite(charBuffNew[5],4, 1);
        }else{
          bitWrite(charBuffNew[5],4, 0);
        }
        if (payload[1] == '1'){
          bitWrite(charBuffNew[5],5, 1);
        }else{
          bitWrite(charBuffNew[5],5, 0);
        }
        if (payload[0] == '1'){
          bitWrite(charBuffNew[5],6, 1);
        }else{
          bitWrite(charBuffNew[5],6, 0);
        }
        //Serial.println(charBuffNew[6],BIN);
      }
      if (topic[13] == 'M'){
        changeWaiting = 1;
        if (payload[0] == '0'){  //Cooling
          bitWrite(charBuffNew[1], 2, 0);
          bitWrite(charBuffNew[1], 3, 0);
          bitWrite(charBuffNew[1], 4, 0);
        }
        if (payload[0] == '1'){  //Dehumidify
          bitWrite(charBuffNew[1], 2, 1);
          bitWrite(charBuffNew[1], 3, 0);
          bitWrite(charBuffNew[1], 4, 0);
        }
        if (payload[0] == '2'){  //Fan only
          bitWrite(charBuffNew[1], 2, 0);
          bitWrite(charBuffNew[1], 3, 1);
          bitWrite(charBuffNew[1], 4, 0);
        }
        if (payload[0] == '3'){  //Auto
          bitWrite(charBuffNew[1], 2, 1);
          bitWrite(charBuffNew[1], 3, 1);
          bitWrite(charBuffNew[1], 4, 0);
        }
        if (payload[0] == '4'){  //Heating
          bitWrite(charBuffNew[1], 2, 0);
          bitWrite(charBuffNew[1], 3, 0);
          bitWrite(charBuffNew[1], 4, 1);
        }
      }
      if (topic[13] == 'T'){
        //Serial.println("Temp");
        changeWaiting = 1;
        char tmpChar[3] = {payload[0],payload[1], '\0'};  // Convert it to a null terminated string.
        unsigned int tempval = atoi(tmpChar)-15;  // Take off the offset of 15 Degrees.
        bitWrite(charBuffNew[6], 0, bitRead(tempval, 0));  // Write the bits
        bitWrite(charBuffNew[6], 1, bitRead(tempval, 1));
        bitWrite(charBuffNew[6], 2, bitRead(tempval, 2));
        bitWrite(charBuffNew[6], 3, bitRead(tempval, 3));
      }
      if (topic[13] == 'F'){
        changeWaiting = 1;
        if (payload[0] == '0'){  //Low
          bitWrite(charBuffNew[1],5,0);
          bitWrite(charBuffNew[1],6,0);
        }
        if (payload[0] == '1'){  //Med
          bitWrite(charBuffNew[1],5,1);
          bitWrite(charBuffNew[1],6,0);
        }
        if (payload[0] == '2'){  //High
          bitWrite(charBuffNew[1],5,0);
          bitWrite(charBuffNew[1],6,1);
        }
      }
      if (topic[13] == 'P'){
        changeWaiting = 1;
        //Serial.println("Power");
        if (payload[0] == '1'){
          bitWrite(charBuffNew[1],1,1);
        }else{
          bitWrite(charBuffNew[1],1,0);
        }
      }
    }
}

byte calcChecksum(){
  unsigned int checksum;
  checksum2 = 0;
  for (int i = 0; i < 12; i++){
    //Serial.print(charBuff[i]);
    //Serial.print(".");
    checksum2 = checksum2 + charBuffNew[i];
  }

    checksum = checksum2 ^ 0x55;
    return checksum - 256;
}

void serialFlush(){
  while(swSer.available() > 0) {
    char t = swSer.read();
  }
} 


void sendConfig(){
  charBuffNew[0] = 40;  // Slave
  charBuffNew[2] = 0;   //Clear out any other misc bits.
  charBuffNew[3] = 0;   //we dont need
  charBuffNew[4] = 0;
  charBuffNew[8] = 0;
  charBuffNew[9] = 0;
  charBuffNew[10] = 0;
  charBuffNew[11] = 0;
  
  //Calculate the checksum for the data
  charBuffNew[12] = calcChecksum();

  //Send it of to the AC
  Serial.println("Sending to AC");

  // ******* Disable serial RX
  swSer.write(charBuffNew,13);
  // ******* Enable serial RX
  
  // Make sure we are not listening to the data we sent - Prurge any data in the RX buffer.
  serialFlush();
}

void mqttConnect() {
  if (!MQTTClient.connected()) {
    Serial.println("Connecting to broker");
    if (MQTTClient.connect(id)){
      Serial.print("Subscribing to :");
      Serial.println(subPath);
      MQTTClient.subscribe(subPath);
    }else{
      Serial.println("Failed to connect!");
    }
  }
}


void publishTopicValue(char* strString, char* value) {
  Serial.print("S:");
  Serial.print(strString);
  Serial.print("/");
  Serial.println(value);
  MQTTClient.publish(strString, value);
}

void publishSettings(){
  //Power
  powerByte = bitRead(charBuff[1],1);

  // Fan speed 0-2 = Low, Med, High
  bitWrite(fanByte, 0, bitRead(charBuff[1],5));
  bitWrite(fanByte, 1, bitRead(charBuff[1],6));

  //Mode 0 = Cool, 1 = Dehumidify, 2 = Fan only, 3 = Auto, 4 = Heat
  bitWrite(modeByte,0, bitRead(charBuff[1],2));
  bitWrite(modeByte,1, bitRead(charBuff[1],3));
  bitWrite(modeByte,2, bitRead(charBuff[1],4));

  //Set Temp - Binary 0011 -> 1111 = 18 - 30 Deg (decimal 3 offset in value, starts at 18, possibly cool can be set at 15?)
  bitWrite(tempByte,0, bitRead(charBuff[6],0));
  bitWrite(tempByte,1, bitRead(charBuff[6],1));
  bitWrite(tempByte,2, bitRead(charBuff[6],2));
  bitWrite(tempByte,3, bitRead(charBuff[6],3));

  //Zone control - Single bits for each zone
  bitWrite(zoneByte,0, bitRead(charBuff[5],3)); //Zone 4
  bitWrite(zoneByte,1, bitRead(charBuff[5],4)); //Zone 3
  bitWrite(zoneByte,2, bitRead(charBuff[5],5)); //Zone 2
  bitWrite(zoneByte,3, bitRead(charBuff[5],6)); //Zone 1

  char strPath1[] = {'h', 'a', '/', 'm', 'o', 'd', '/', id[0], id[1], id[2], id[3], '/', 'P','\0'};  // Power State
  char strPath2[] = {'h', 'a', '/', 'm', 'o', 'd', '/', id[0], id[1], id[2], id[3], '/', 'T','\0'};  //Set Temp
  char strPath3[] = {'h', 'a', '/', 'm', 'o', 'd', '/', id[0], id[1], id[2], id[3], '/', 'M','\0'};  //Mode
  char strPath4[] = {'h', 'a', '/', 'm', 'o', 'd', '/', id[0], id[1], id[2], id[3], '/', 'Z','\0'};  //Zones
  char strPath5[] = {'h', 'a', '/', 'm', 'o', 'd', '/', id[0], id[1], id[2], id[3], '/', 'F','\0'};  //Fan

  char tempChar[2] = {powerByte + 48, '\0'};
  publishTopicValue(strPath1,tempChar);
  
  tempChar[0] = modeByte + 48;
  publishTopicValue(strPath3,tempChar);

  tempChar[0] = fanByte + 48;
  publishTopicValue(strPath5,tempChar);

  char charStr[5] = {bitRead(zoneByte,3)+48, bitRead(zoneByte,2)+48, bitRead(zoneByte,1)+48, bitRead(zoneByte,0)+48, '\0'};
  publishTopicValue(strPath4,charStr);

  char tmpChar[3];
  char* myPtr = &tmpChar[0];
  snprintf(myPtr, 3, "%02u", tempByte+15);
  publishTopicValue(strPath2,tmpChar);
  lastChecksum = charBuff[12];
}

//***********************************************

void setup() {
  EEPROM.begin(512);
  Serial.begin(115200);

  if (!ReadConfig())
  {
    // DEFAULT CONFIG
    config.ssid = "JCB_5G";
    config.password = "mywifipassword";
    config.dhcp = true;
    config.IP[0] = 192;config.IP[1] = 168;config.IP[2] = 0;config.IP[3] = 185;
    config.Netmask[0] = 255;config.Netmask[1] = 255;config.Netmask[2] = 255;config.Netmask[3] = 0;
    config.Gateway[0] = 192;config.Gateway[1] = 168;config.Gateway[2] = 1;config.Gateway[3] = 1;
    config.mqttserver = "192.168.0.116";
    config.hostname = "AC_Controls";
    WriteConfig();
    Serial.println("General config applied");
  }

  WiFi.mode(WIFI_STA); // Client Mode
  ConfigureWifi();

  //OTA stuff
  ArduinoOTA.setHostname("AC_Controller");
  ArduinoOTA.onError([](ota_error_t error) { ESP.restart(); });
  ArduinoOTA.setPassword((const char *)"anotherpassword");
  ArduinoOTA.begin();

  char *mqtt_server = &config.mqttserver[0u]; //Convert the server string to char array for mqtt client
  
  MQTTClient.setServer(mqtt_server, 1883);
  MQTTClient.setCallback(callback);

  //Set up software serial at 104 baud to talk to AC
  swSer.begin(104,SWSERIAL_8N1,5,4);

  Serial.println("All your AC belong to us");
}

void loop() {
  unsigned long currentMillis = millis();

  //Make sure we are connected to MQTT
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    // Make sure we are connected
    if (WiFi.status() != WL_CONNECTED) {
      ConfigureWifi();
    }
    ArduinoOTA.handle();
    mqttConnect();
  }
   
   if((millis() - previousMQTTCommand > waitForCommand) && (changeWaiting == 1)) {  //We have received one or more updates via MQTT
      //We have received some updates and we need to send them off via serial.

     // how long since last Master update?
     int lastMasterTime = millis() - lastMasterRx;
     int lastHeadTime = millis() - lastHeadRx;
     if (lastMasterTime > 1000 && lastMasterTime < 8000 && lastHeadTime < 50000){
       sendConfig();
       delay(200);
       sendConfig();  //Twice, just to be sure (This is how the factory unit operates...)
       changeWaiting = 0;
     }
   }
   
   MQTTClient.loop();

   if (swSer.available()) { 
     lastCharTime=millis();
     charBuff[charCount] = swSer.read();
     charCount++;
     if (charCount == 13){
       Serial.print("R: ");
       for (int i=0; i < 12; i++){
         Serial.print(charBuff[i],DEC);
         Serial.print(",");  
       }
       Serial.println(charBuff[12],DEC);
       charCount = 0;
       
       if (charBuff[0] == 168){ //Only publish data back to MQTT from the Master controller.
         lastMasterRx = millis(); //Track when we received the last 168 (master) packet
         publishSettings();  //Push it to MQTT
       }
       if (charBuff[0] == 200){  //Track when we received the last 200 (Head unit) packet.
        lastHeadRx = millis();
       }
     }
  }

  if (charCount < 13 && millis() - lastCharTime > 100){
    charCount = 0;  //Expired or we got half a packet. Ignore
  }
}

Any ideas what's going wrong for me???

TIA,
Josh

The first thing that I would do is to remove all of teh code except for that which connects to WiFi and connects to the broker

id['F','F','F','F','\0'];

What does this line of code do ?

No idea what it does... but just did some googling for opther mqtt code and found that the setserver line on line 349 is being converted using the cvhar command whereas it can just be put in inside brackets... changed it from

char *mqtt_server = &config.mqttserver[0u]; //Convert the server string to char array for mqtt client
MQTTClient.setServer(mqtt_server, 1883);

to

MQTTClient.setServer("192.168.0.116", 1883);

and now it connects and subscribed...

Curious. Not seeing the definition for the config structure, it is difficult to determine, but I wondered whether either those text elements should be null terminated, i.e.:

config.mqttserver = "192.168.0.116\0";

OR, if those elements are of type String, then could this have just been used:

MQTTClient.setServer(mqtt_server.toCharArray, 1883);

rather than converting to a *char?

Also, why is this including SoftwareSerial? Is it using GPIO pin for serial communications?

changing the set server to just my mqtt server adress instead of the char* version fixed it's connectivity.

As for the software serial... yes, it communicates at 104baud to my AC controller... only issue im having is finding what pin it is supposed to be using... im not sure if i have breadboarded it up properly now because it isnt recieving or sending any signal to the AC unit... (i can successfully negotiate the MQTT broker so assume its getting that info now)

Can you see in the code (written by another for an arduino board) what pics it specifies? Ive searched pinmode and digitalread but it isnt in the code anywhere....

SoftwareSerial swSer;

You appear to have defined a SoftwareSerial object named swSer without defining the pins that it uses

The syntax is

SoftwareSerial swSer(rxPin, txPin;

Where the 2 parameters are pins of your choice

I thought the same when I looked up software serial, but I found this further down which sets the baud and the pins i think?


swSer.begin(104,SWSERIAL_8N1,5,4);

I don't recall having seen that syntax used before, but it may be valid for the ESP8266 variant of SoftwareSerial, which I have never used

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.