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