/* AC Interface to MQTT based on https://github.com/adaasch/AC-hack*/ /* TYWE1S - flash by hardware interface to the AC Controler /* Compile for Generic ESP8266 /**************************************************************** * * Web Interface * MQTT Server * Serial Comm with GPIO 13,15, 9600 8E1 * * * Compile Date ***************************************************************/ #include #include #include #include #include #include #include #include #include #include const char* host = "Klimaanlage"; //const char* ssid = "****"; const char* ssid = "****"; const char* password = "*****"; unsigned long StartZeit; String req,t; String mqtopic="Klima/Funktion"; int Sekunde,Sekunde0,Minute, Stunde,reconnects,rlen; byte rec_a[80]; byte trx_a[]={0xBB, 0x00, 0x01, 0x04, 0x02, 0x01, 0x00, 0xBD}; byte snd_a[]={0xBB, 0x00, 0x01, 0x03, 0x1D, 0x00, 0x00, 0x64, 0x01, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18}; byte speeds[]={0, 2, 6, 3, 7, 5}; String speed$[]={"Auto", "1", "2", "3", "4", "5"}; byte modes[]={3, 7, 2, 1, 8}; String mode$[]={"Cooling", "Ventilation", "Drying", "Heating", "Auto"}; byte pwr=0, eco=0, tbo=0, mpwr, meco, mtbo, weco, wpwr, wtbo; byte csum, cnt, md=4, spd=1, mmd, mspd, wmd, wspd, halbe; float tset=21, troom, tpipe, tout, topipe, mtset, wtset; //Static IP address configuration IPAddress ip(192, 168, 0, 144); //ESP static ip IPAddress gateway(192, 168, 0, 1); //IP Address of your WiFi Router (Gateway) IPAddress subnet(255, 255, 255, 0); //Subnet mask IPAddress dns(8, 8, 8, 8); //DNS IPAddress dns2(8, 8, 4, 4); //DNS ESP8266WebServer httpServer(80); ESP8266HTTPUpdateServer httpUpdater; unsigned int localPort = 2390; // local port to listen for UDP packets #define MQTT_SERVER "192.168.0.140" WiFiClient KlimaClient; WiFiServer server(80); //Service Port int status = WL_IDLE_STATUS; PubSubClient client(MQTT_SERVER, 1883, KlimaClient); PubSubClientTools mqtt(client); StaticJsonDocument<100> doc; //************************************************************************************** void setup() { // Start serial Out Serial.begin(9600,SERIAL_8E1); //Verbinden mit Wifi WiFi.config(ip, gateway, subnet, dns, dns2); WiFi.mode(WIFI_STA); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); delay(500); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } WiFi.config(ip, gateway, subnet, dns, dns2); Serial.printf("Wi-Fi mode set to WIFI_STA %s\n", WiFi.mode(WIFI_STA) ? "" : "Failed!"); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); // Start the webserver MDNS.begin(host); server.begin(); MDNS.addService("http", "tcp", 80); Serial.println("Server started"); delay(3000); reconnects=0; // Connect to MQTT if (!client.connected()) { // MQTT Client if (client.connect("ACClient","MyMQTT","")) { //Serial.print("MQTT Connected"); mqtt.subscribe(mqtopic,topic1_subscriber); } } // Verbindung zur Klimaanlage Serial.println("Switch to SerialKlima"); Serial.swap(); delay(200); read_AC(); } void loop() { client.loop(); //MQTT if(millis()>StartZeit+1000) // once every second { Sekunde++; if(Sekunde>60) { // once every 60 sec Sekunde=0; Minute++; if (WiFi.localIP()!= ip) WiFi.config(ip, gateway, subnet, dns, dns2); // force ip if (!client.connected()) { // MQTT Client if (client.connect("ACClient","MyMQTT","")) { //Serial.print("MQTT Connected"); mqtt.subscribe(mqtopic,topic1_subscriber); reconnects++; t=""; t= t + "T:" + (millis()/1000)+ " R:"+ reconnects; mqtt.publish("Klima/MQTT", t ); } } read_AC(); // and publish result to mqtt } if(Minute>60) { // once every h Minute=0; } StartZeit=StartZeit+1000; website(); } } //end of loop void website() { // Check if a client has connected WiFiClient client = server.available(); if (client) { String req = client.readStringUntil('\r'); if (req != "") { React(req); // Prepare the WEB response String s = "" "" "" "" "" "Klimaanlage"; s+=""; s+=""; s+= ""; s+= "
"; s+= "

Status:"" "; s+= mode$[md-1]; s+= "

"; s+= "Set Temp [°C]: "; s+= tset; s+= "
\n" " Lüfter Speed: "; s+= speed$[spd-1]; s+= "
\n" " Temper. Raum [°C]: "; s+= troom; s+= "
\n" " Temper. WT Innen [°C]: "; s+= tpipe; s+= "
\n" " Temper. Aussen [°C]: "; s+= tout; s+= "
\n" " Temper. WT Aussen [°C]: "; s+= topipe; s+= "
"; s+= "\n"; // Send the response to the client client.print(s); client.println("

Funktionen:

"); // // buttons if (wpwr== 0) client.println(""); if (wpwr== 1) client.println(""); if (weco==0) client.println(""); if (weco==1) client.println(""); if (wtbo==0) client.println(""); if (wtbo==1) client.println(""); client.println("
FW Update:
"); s+= "
\n"; s= " "; s+= " Reconnects: "; s+= reconnects; ;s+= Minute; client.print(s); client.println(""); client.println(""); } client.flush(); } // no client } void Page_Service() { int cnt=0; service_loop: cnt++; if (cnt<2000) { delay(30); httpServer.handleClient(); goto service_loop; } ESP.reset(); } void React(String Request) { // Match the request SetTemp if (Request.indexOf("Power")!= -1) { if (wpwr==1) wpwr=0; else wpwr=1; send_AC(wpwr,255,0,255,255,255,255); } else if (Request.indexOf("SetTemp")!= -1) { ;send_AC(255,wtset,0,255,255,255,255); } else if (Request.indexOf("Speed")!= -1) { } else if (Request.indexOf("Eco")!= -1) { if (weco==1) weco=0; else weco=1; send_AC(255,255,0,255,weco,255,255); } else if (Request.indexOf("Turbo")!= -1) { if (wtbo==1) wtbo=0; else wtbo=1; send_AC(255,255,0,255,255,wtbo,255); } else if (Request.indexOf("Mode")!= -1) { } else if (Request.indexOf("Reset")!= -1) { //Serial.print("Reset\n"); ESP.reset(); } else if (Request.indexOf("update")!= -1) { server.stop(); httpUpdater.setup(&httpServer); httpServer.begin(); Page_Service(); server.begin(); } else { } } // End of Reaction void send_AC(byte spwr, byte stset, byte shalbe, byte sspd, byte seco, byte stbo, byte smd) { // mqtt.publish("Klima/toAC", t+"{\"Power\":" +spwr + ",\n\"Set-Temp\":" +stset + ",\"eco\":" +seco + ",\"Turbo\":" +stbo + ",\"Speed\":" +sspd + ",\"Mode\":" +smd + "}"); if (spwr<2) snd_a[7]=(snd_a[7]&0xFB)|(4*spwr); else snd_a[7]=(snd_a[7]&0xFB)|(4*pwr); if (smd<6) snd_a[8]=(snd_a[8]&0xF0)|(modes[smd-1]); else snd_a[8]=(snd_a[8]&0xF0)|(modes[md-1]); if (stbo<2) snd_a[8]=(snd_a[8]&0xBF)|(0x40*stbo); else snd_a[8]=(snd_a[8]&0xBF)|(0x40*tbo); if (seco<2) snd_a[7]=(snd_a[7]&0x7F)|(0x80*seco); else snd_a[7]=(snd_a[7]&0x7F)|(0x80*eco); if (stset<32 and stset >15) { snd_a[9]=0x6F-stset; if (shalbe==1) snd_a[11]=snd_a[11]|(0x02); else snd_a[11]=snd_a[11]&(0xFD); } else { snd_a[9]=0x6F-tset; } if (sspd <6) snd_a[10]=speeds[sspd]; else snd_a[10]=speeds[spd]; csum=0; for (cnt=0; cnt <= 33; cnt++){ csum=csum^snd_a[cnt]; t=t+String(snd_a[cnt], HEX) +" "; } snd_a[34]=csum; Serial.write(snd_a, 35); delay(700); read_AC(); //mqtt.publish("Klima/toAC", t); t=""; } void topic1_subscriber(String topic, String message) { deserializeJson(doc, message); mpwr=255; if (message.indexOf("Power")!= -1) mpwr=doc["Power"]; mtset=255; if (message.indexOf("Set-Temp")!= -1) mtset=doc["Set-Temp"]; halbe=mtset; if (mtset-halbe !=0) halbe=1; else halbe=0; mspd=255; if (message.indexOf("Speed")!= -1) mspd=doc["Speed"]; meco=255; if (message.indexOf("Eco")!= -1) meco=doc["Eco"]; mtbo=255; if (message.indexOf("Turbo")!= -1) mtbo=doc["Turbo"]; mmd=255; if (message.indexOf("Mode")!= -1) mmd=doc["Mode"]; //mqtt.publish("Klima/received", t+"{\"Power\":" +mpwr + ",\n\"Set-Temp\":" +mtset + ",\"Eco\":" +meco + ",\"Turbo\":" +mtbo + ",\"Speed\":" +mspd + ",\"Mode\":" +mmd + "}"); send_AC(mpwr,mtset,halbe,mspd,meco,mtbo,mmd); } void read_AC() { byte Index, zahl; if (Serial.available() ==0) { Serial.write(trx_a, 8); delay(300); } else { Index=0; rec_a[0] = Serial.read(); if (rec_a[0] == 0xBB) //Framestart { while (Serial.available()>0) { Index++; if (Index>80) goto full; rec_a[Index] = Serial.read(); } } } full: if (rec_a[0] ==0xBB and rec_a[1]==1){ tset=(rec_a[8]&0x0F)+16+((rec_a[9]&0x02)*0.25); halbe=((rec_a[9]&0x02)*0.5); if ((rec_a[7]&0x10) >0) pwr=1; else pwr=0; if ((rec_a[7]&0x40) >0) eco=1; else eco=0; if ((rec_a[7]&0x80) >0) tbo=1; else tbo=0; md= (rec_a[7]&0x0F); zahl=(rec_a[8]&0xF0); if(zahl==0x80) spd= 0; if(zahl==0x90) spd= 1; if(zahl==0xC0) spd= 2; if(zahl==0xA0) spd= 3; if(zahl==0xD0) spd= 4; if(zahl==0xB0) spd= 5; troom=(rec_a[17]-65)/2; tpipe=(rec_a[30]-65)/2; topipe=rec_a[37]-16; tout=rec_a[36]-16; wpwr=pwr; wtset=tset; weco=eco; wtbo=tbo; wspd=spd; for (cnt=36; cnt <= 37; cnt++){ t=t+ ",\n\"" +cnt + "\":" + (rec_a[cnt]); } //mqtt.publish("Klima/fromAC", "{\"Test\":0" + t+ "\n}"); t=""; } //mqtt.publish("Klima/Status", t+"{\"Power\":" +pwr + ",\n\"Set-Temp\":" +tset + ",\n\"Room-Temp\":" +troom + ",\n\"WT-Temp\":" +tpipe + ",\n\"Eco\":" +eco + ",\n\"Turbo\":" +tbo + ",\n\"Speed\":" +spd + ",\n\"Mode\":" +md + "}"); mqtt.publish("Klima/Status", t+"{\"Power\":" +pwr + ",\"Set-Temp\":" +tset + ",\"Room-Temp\":" +troom + "}"); }