ESP8266 loses MQTT connection or crashes?!

Good evening,

I started making my Jura coffeemaker “smart”, but stumbled upon some problems.
As it will work properly, I can post that whole project in the Tutorials page. But for now I have to figure out what my problem is.

I’m using the ESP8266 (Wemos D1 board). Reading serial messages from the coffeemachine and communicating with openhab through MQTT.
I have also some problems with the timing for the communication with the coffeemaker, but my main problem is the MQTT connection. It loses the connection almost every 2-3 minutes and wont send updates after a few hours. At this point it also won’t accept all commands.

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

const char* wifi_ssid =    	"SSID";
const char* wifi_key =    	"WIFIPASSWORD";
const char* mqtt_client =  	"JURAF90";
const char* mqtt_server =  	"1.2.3.4";
const char* mqtt_user =    	"user";
const char* mqtt_password =	"password";

WiFiClient      espClient;
PubSubClient    client(espClient);
SoftwareSerial  jura(12, 13);

unsigned long	previousMillis = 0;	// will store last time loop ran
unsigned int 	interval = 500;		// interval at which to limit loop
unsigned int 	loopCount = 0;		// resets loop

byte intra = 1;
byte inter = 10;

String power_state;
char size_state;
char aroma_state;


void setup() {
	pinMode(BUILTIN_LED, OUTPUT); 	// set onboard LED as output
	Serial.begin(115200);         	// Set connection to debugging
	jura.begin(9600);       		// Set connection to Jura
	setup_wifi();         			// wifi configuration
	client.setServer(mqtt_server, 1883);
	client.setCallback(mqttcallback);  
}


void setup_wifi() {
	Serial.print(F("[INFO][WIFI] Connecting to "));
	Serial.println(wifi_ssid);
	WiFi.persistent(false);
	WiFi.mode(WIFI_STA);
	WiFi.hostname("JURAF90");
	WiFi.begin(wifi_ssid, wifi_key);
	while (WiFi.status() != WL_CONNECTED) {
		delay(500);
		Serial.print(".");
	}
	Serial.println("");
	Serial.println(F("[INFO][WIFI] Connected"));  
	Serial.print(F("[INFO][WIFI] IP address: "));
	Serial.println(WiFi.localIP());
}

boolean reconnect() {
	if(WiFi.status() != WL_CONNECTED){
		Serial.println(F("[INFO][WIFI] Reconnecting..."));
		while (WiFi.status() != WL_CONNECTED){
			WiFi.begin(wifi_ssid, wifi_key);
			uint8_t timeout = 8;
			while (timeout && (WiFi.status() != WL_CONNECTED)) {
				timeout--;
				delay(100);
			}
		}
	}
	if(!client.connected()){
		Serial.println(F("[INFO][MQTT] Connecting..."));
		while(!client.connected()){
			client.connect(mqtt_client, mqtt_user, mqtt_password);
			uint8_t timeout = 8;
			while (timeout && (!client.connected())){
				timeout--;
				delay(1000);
			}
			if(client.connected()){
				Serial.println(F("[INFO][MQTT] Subscribing started..."));
				client.subscribe("JURAF90/power/cmd");     	// Subscription 
				client.subscribe("JURAF90/size/cmd");    	// Subscription 
				client.subscribe("JURAF90/aroma/cmd");    	// Subscription 
				client.subscribe("JURAF90/function/cmd");   // Subscription 
				client.subscribe("JURAF90/debug/cmd");     	// Subscription 
			}
		}
	}
}


void mqttcallback(char* topic, byte* payload, unsigned int length) {
	payload[length] = '\0';
	// Serial.print(F("[DEBUG][MQTT][cmd]"));
	// Serial.println((char*)payload);
	if (strcmp(topic, "JURAF90/power/cmd") == 0) {
		if(strcmp((char*)payload, "ON") == 0){
			toCoffeemaker("AN:01");
			Serial.println(F("[INFO][MQTT][cmd] ON"));
		}
		else if (strcmp((char*)payload, "OFF") == 0) {
			toCoffeemaker("AN:02");
			Serial.println(F("[INFO][MQTT][cmd] OFF"));
		}
	}
	else if (strcmp(topic, "JURAF90/size/cmd") == 0) {
		if(strcmp((char*)payload, "ESPRESSO") == 0){
			toCoffeemaker("FA:0F");
			Serial.println(F("[INFO][MQTT][cmd] ESPRESSO"));
		}
		else if(strcmp((char*)payload, "COFFEE") == 0){
			toCoffeemaker("FA:0E");
			Serial.println(F("[INFO][MQTT][cmd] COFFEE"));
		} 
		else if(strcmp((char*)payload, "BIGCUP") == 0){
			toCoffeemaker("FA:0D");
			Serial.println(F("[INFO][MQTT][cmd] BIGCUP"));
		}
	}
	else if (strcmp(topic, "JURAF90/aroma/cmd") == 0) {
		if(strcmp((char*)payload, "MILD") == 0){
			toCoffeemaker("FA:10");
			Serial.println(F("[INFO][MQTT][cmd] MILD"));
		}
		else if(strcmp((char*)payload, "NORMAL") == 0){
			toCoffeemaker("FA:11");
			Serial.println(F("[INFO][MQTT][cmd] NORMAL"));
		}
		else if(strcmp((char*)payload, "STRONG") == 0){
			toCoffeemaker("FA:12");
			Serial.println(F("[INFO][MQTT][cmd] STRONG"));
		}
	}
	else if (strcmp(topic, "JURAF90/function/cmd") == 0) {
		if(strcmp((char*)payload, "START") == 0){
			toCoffeemaker("FA:19");
			Serial.println(F("[INFO][MQTT][cmd] START"));
		}
		else if(strcmp((char*)payload, "WATER") == 0){
			toCoffeemaker("FA:0A");
			Serial.println(F("[INFO][MQTT][cmd] WATER"));
		}
		else if(strcmp((char*)payload, "STEAM") == 0){
			toCoffeemaker("FA:09");
			Serial.println(F("[INFO][MQTT][cmd] STEAM"));
		}
		else if (strcmp((char*)payload, "RINSE") == 0) {
			toCoffeemaker("FA:02");
			Serial.println(F("[INFO][MQTT][cmd] RINSE"));
		}
		else if (strcmp((char*)payload, "LIGHT") == 0) {
			toCoffeemaker("FA:08");
			Serial.println(F("[INFO][MQTT][cmd] LIGHT"));
		}
		//else{
		//	Serial.print(F("[INFO][MQTT][cmd] "));
		//	Serial.println((char*)payload);
		//}
	}
	else if (strcmp(topic, "JURAF90/debug/cmd") == 0) {  
		if(strcmp((char*)payload, "SCAN_RR") == 0){
			Serial.println(F("[MQTT-DEBUG] Scan RR:"));
			int i;
			String result;
			for (int i = 0; i < 256; i++){
				char textBuf[256];
				sprintf(textBuf, "RR:%02X", i);
				toCoffeemaker(textBuf);
				delay(200);
				Serial.print(textBuf);
				Serial.print(F(" : "));
				Serial.println(fromCoffeemaker());
				delay(50);
			}
		}
		else if(strcmp((char*)payload, "SCAN_RE") == 0){
			Serial.println(F("[MQTT-DEBUG] Scan RE:"));
			int i;
			String result;
			for (int i = 0; i < 256; i++){
				char textBuf[256];
				sprintf(textBuf, "RE:%02X", i);
				toCoffeemaker(textBuf);
				delay(200);
				Serial.print(textBuf);
				Serial.print(F(" : "));
				Serial.println(fromCoffeemaker());
				delay(100);
			}
		}
		else{
			Serial.println(F("[MQTT-DEBUG] Received command: "));
			toCoffeemaker((char*)payload);
			Serial.print((char*)payload);
			Serial.print(F(" : "));
			Serial.println(fromCoffeemaker());
		}
	}  
}


void loop() {
	if(millis() - previousMillis > interval) {
		loopCount ++;
		previousMillis = millis();
	}
	reconnect();
	if (loopCount == 7) {  // Check the status every 7 seconds
		loopCount = 0;
		readState();
	}
	delay(100);
	client.loop();
}


char toCoffeemaker(String outbytes) {
	while (jura.available()) {
		jura.read();
	}
	byte z0, z1, z2, z3;
	outbytes += "\r\n";
	for (int i = 0; i < outbytes.length(); i++) {
		z0 = 255;
		z1 = 255;
		z2 = 255;
		z3 = 255;
		// Reads bits of ASCII byte and writes it into coding bits of 4 UART bytes  
		bitWrite(z0, 2, bitRead(outbytes[i],0));
		bitWrite(z0, 5, bitRead(outbytes[i],1));
		bitWrite(z1, 2, bitRead(outbytes[i],2));  
		bitWrite(z1, 5, bitRead(outbytes[i],3));
		bitWrite(z2, 2, bitRead(outbytes[i],4));
		bitWrite(z2, 5, bitRead(outbytes[i],5));
		bitWrite(z3, 2, bitRead(outbytes[i],6));  
		bitWrite(z3, 5, bitRead(outbytes[i],7)); 
		// Sends a 4 byte package to the coffeemaker
		delay (intra); jura.write(z0);
		delay (intra); jura.write(z1);
		delay (intra); jura.write(z2);
		delay (intra); jura.write(z3); 
		delay(inter);
	}
	delay(300);
}


String fromCoffeemaker(){
	char inbyte;
	String inbytes;
	unsigned int w = 0;
	unsigned int s = 0;
	while (!inbytes.endsWith("\r\n")) {
		if (jura.available()) {
			byte rawbyte = jura.read();
			bitWrite(inbyte, s + 0, bitRead(rawbyte, 2));
			bitWrite(inbyte, s + 1, bitRead(rawbyte, 5));
			if ((s += 2) >= 8) {
				s = 0;
				inbytes += inbyte;
			}
		} 
		else {
			delay(inter);
		}
		if (w++ > 500) {
			return "";
		}
	}
	return inbytes.substring(0, inbytes.length() - 2);
}


void readState() {
	String resultState;
	toCoffeemaker("RR:1B");
	resultState = fromCoffeemaker();
	// Serial.print("Ergebnis: ");
	// Serial.println(result);
	if(resultState != power_state && resultState != ""){
		if(resultState == "rr:0000"){
			Serial.println(F("[INFO][JURA] OFF"));
			client.publish("JURAF90/power/state", "OFF");
			power_state = "rr:0000";
		}
		else if(resultState == "rr:1000"){
			Serial.println(F("[INFO][JURA] ON"));
			client.publish("JURAF90/power/state", "ON");
			client.publish("JURAF90/state", "Bitte wählen");
			power_state = "rr:1000";
		}
		else if(resultState == "rr:1001"){
			Serial.println(F("[INFO][JURA] Flushing..."));
			client.publish("JURAF90/state", "Gerät spült");
			power_state = "rr:1001";
		}
		else if(resultState == "rr:1002"){
			Serial.println(F("[INFO][JURA] Cleaning..."));
			client.publish("JURAF90/state", "Gerät reinigt");
			power_state = "rr:1002";
		}
		else if(resultState == "rr:1008"){
			Serial.println(F("[INFO][JURA] Making Coffee..."));
			client.publish("JURAF90/state", "Brüht Kaffee");
			power_state = "rr:1008";
		}
		//else{
		//	Serial.println(F("[INFO][JURA] Bitte die Verbindung zur JURA prüfen"));
		//	client.publish("JURAF90/state", "Verbindung unterbrochen");
		//	Serial.println(result);
		//	power_state = "";
		//}  
	}
	if(power_state == "rr:1000"){ 
		String resultProduct;
		toCoffeemaker("RR:64");
		resultProduct = fromCoffeemaker();
		if(resultProduct != "" && resultProduct[3] != aroma_state){
			if (resultProduct[3] == 51){
				client.publish("JURAF90/aroma/state", "MILD");
				Serial.println(F("[INFO][JURA] Mildes Aroma"));
				aroma_state = 51;
			}
			else if (resultProduct[3] == 53){
				client.publish("JURAF90/aroma/state", "NORMAL");
				Serial.println(F("[INFO][JURA] Normales Aroma"));
				aroma_state = 53;
			}
			else if (resultProduct[3] == 57){
				client.publish("JURAF90/aroma/state", "STRONG");
				Serial.println(F("[INFO][JURA] Starkes Aroma"));
				aroma_state = 57;
			}  
		}
		if(resultProduct != "" && resultProduct[4] != size_state){
			if (resultProduct[4] == 56){
				client.publish("JURAF90/size/state", "ESPRESSO");
				Serial.println(F("[INFO][JURA] Espresso"));
				size_state = 56;
			}
			else if (resultProduct[4] == 52){
				Serial.println(F("[INFO][JURA] Kaffee"));
				client.publish("JURAF90/size/state", "COFFEE");
				size_state = 52;
			}
			else if (resultProduct[4] == 50){
				Serial.println(F("[INFO][JURA] Big Cup"));
				client.publish("JURAF90/size/state", "BIGCUP");
				size_state = 50;
			}
		}
	}
}

Btw: my source was this project in the beginning, but it wasn’t maintained anymore, so I started to do my own development. There are also different other github links I checked when started

I don’t have an answer for you, but I’d like to point to a different mqtt client library, AsyncMqttClient.h. Here’s how I use it, also based off from another tutorial.

I hope this is somewhat helpful.

Do you know this Library is in any way better? But thanks, I’ll try it out!

Nope. I just used it for a few of my devices, and they worked pretty well.