diff --git a/Wetterstation.HMI b/Wetterstation.HMI
index a60d230890cfb6a381f23448640624b82e6ac854..dfc54bf2550c1b2488f437b699c14cc2118bf681 100644
Binary files a/Wetterstation.HMI and b/Wetterstation.HMI differ
diff --git a/wetterstation/PubSubClient.cpp b/wetterstation/PubSubClient.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0fa420d48f088506dd25f928733074c49d7fccca
--- /dev/null
+++ b/wetterstation/PubSubClient.cpp
@@ -0,0 +1,653 @@
+/*
+  PubSubClient.cpp - A simple client for MQTT.
+  Nick O'Leary
+  http://knolleary.net
+*/
+
+#include "PubSubClient.h"
+#include "Arduino.h"
+
+PubSubClient::PubSubClient() {
+    this->_state = MQTT_DISCONNECTED;
+    this->_client = NULL;
+    this->stream = NULL;
+    setCallback(NULL);
+}
+
+PubSubClient::PubSubClient(Client& client) {
+    this->_state = MQTT_DISCONNECTED;
+    setClient(client);
+    this->stream = NULL;
+}
+
+PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) {
+    this->_state = MQTT_DISCONNECTED;
+    setServer(addr, port);
+    setClient(client);
+    this->stream = NULL;
+}
+PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) {
+    this->_state = MQTT_DISCONNECTED;
+    setServer(addr,port);
+    setClient(client);
+    setStream(stream);
+}
+PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
+    this->_state = MQTT_DISCONNECTED;
+    setServer(addr, port);
+    setCallback(callback);
+    setClient(client);
+    this->stream = NULL;
+}
+PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
+    this->_state = MQTT_DISCONNECTED;
+    setServer(addr,port);
+    setCallback(callback);
+    setClient(client);
+    setStream(stream);
+}
+
+PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) {
+    this->_state = MQTT_DISCONNECTED;
+    setServer(ip, port);
+    setClient(client);
+    this->stream = NULL;
+}
+PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream) {
+    this->_state = MQTT_DISCONNECTED;
+    setServer(ip,port);
+    setClient(client);
+    setStream(stream);
+}
+PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
+    this->_state = MQTT_DISCONNECTED;
+    setServer(ip, port);
+    setCallback(callback);
+    setClient(client);
+    this->stream = NULL;
+}
+PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
+    this->_state = MQTT_DISCONNECTED;
+    setServer(ip,port);
+    setCallback(callback);
+    setClient(client);
+    setStream(stream);
+}
+
+PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) {
+    this->_state = MQTT_DISCONNECTED;
+    setServer(domain,port);
+    setClient(client);
+    this->stream = NULL;
+}
+PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream) {
+    this->_state = MQTT_DISCONNECTED;
+    setServer(domain,port);
+    setClient(client);
+    setStream(stream);
+}
+PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
+    this->_state = MQTT_DISCONNECTED;
+    setServer(domain,port);
+    setCallback(callback);
+    setClient(client);
+    this->stream = NULL;
+}
+PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
+    this->_state = MQTT_DISCONNECTED;
+    setServer(domain,port);
+    setCallback(callback);
+    setClient(client);
+    setStream(stream);
+}
+
+boolean PubSubClient::connect(const char *id) {
+    return connect(id,NULL,NULL,0,0,0,0,1);
+}
+
+boolean PubSubClient::connect(const char *id, const char *user, const char *pass) {
+    return connect(id,user,pass,0,0,0,0,1);
+}
+
+boolean PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) {
+    return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage,1);
+}
+
+boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) {
+    return connect(id,user,pass,willTopic,willQos,willRetain,willMessage,1);
+}
+
+boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession) {
+    if (!connected()) {
+        int result = 0;
+
+        if (domain != NULL) {
+            result = _client->connect(this->domain, this->port);
+        } else {
+            result = _client->connect(this->ip, this->port);
+        }
+        if (result == 1) {
+            nextMsgId = 1;
+            // Leave room in the buffer for header and variable length field
+            uint16_t length = MQTT_MAX_HEADER_SIZE;
+            unsigned int j;
+
+#if MQTT_VERSION == MQTT_VERSION_3_1
+            uint8_t d[9] = {0x00,0x06,'M','Q','I','s','d','p', MQTT_VERSION};
+#define MQTT_HEADER_VERSION_LENGTH 9
+#elif MQTT_VERSION == MQTT_VERSION_3_1_1
+            uint8_t d[7] = {0x00,0x04,'M','Q','T','T',MQTT_VERSION};
+#define MQTT_HEADER_VERSION_LENGTH 7
+#endif
+            for (j = 0;j<MQTT_HEADER_VERSION_LENGTH;j++) {
+                buffer[length++] = d[j];
+            }
+
+            uint8_t v;
+            if (willTopic) {
+                v = 0x04|(willQos<<3)|(willRetain<<5);
+            } else {
+                v = 0x00;
+            }
+            if (cleanSession) {
+                v = v|0x02;
+            }
+
+            if(user != NULL) {
+                v = v|0x80;
+
+                if(pass != NULL) {
+                    v = v|(0x80>>1);
+                }
+            }
+
+            buffer[length++] = v;
+
+            buffer[length++] = ((MQTT_KEEPALIVE) >> 8);
+            buffer[length++] = ((MQTT_KEEPALIVE) & 0xFF);
+
+            CHECK_STRING_LENGTH(length,id)
+            length = writeString(id,buffer,length);
+            if (willTopic) {
+                CHECK_STRING_LENGTH(length,willTopic)
+                length = writeString(willTopic,buffer,length);
+                CHECK_STRING_LENGTH(length,willMessage)
+                length = writeString(willMessage,buffer,length);
+            }
+
+            if(user != NULL) {
+                CHECK_STRING_LENGTH(length,user)
+                length = writeString(user,buffer,length);
+                if(pass != NULL) {
+                    CHECK_STRING_LENGTH(length,pass)
+                    length = writeString(pass,buffer,length);
+                }
+            }
+
+            write(MQTTCONNECT,buffer,length-MQTT_MAX_HEADER_SIZE);
+
+            lastInActivity = lastOutActivity = millis();
+
+            while (!_client->available()) {
+                unsigned long t = millis();
+                if (t-lastInActivity >= ((int32_t) MQTT_SOCKET_TIMEOUT*1000UL)) {
+                    _state = MQTT_CONNECTION_TIMEOUT;
+                    _client->stop();
+                    return false;
+                }
+            }
+            uint8_t llen;
+            uint16_t len = readPacket(&llen);
+
+            if (len == 4) {
+                if (buffer[3] == 0) {
+                    lastInActivity = millis();
+                    pingOutstanding = false;
+                    _state = MQTT_CONNECTED;
+                    return true;
+                } else {
+                    _state = buffer[3];
+                }
+            }
+            _client->stop();
+        } else {
+            _state = MQTT_CONNECT_FAILED;
+        }
+        return false;
+    }
+    return true;
+}
+
+// reads a byte into result
+boolean PubSubClient::readByte(uint8_t * result) {
+   uint32_t previousMillis = millis();
+   while(!_client->available()) {
+     yield();
+     uint32_t currentMillis = millis();
+     if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)){
+       return false;
+     }
+   }
+   *result = _client->read();
+   return true;
+}
+
+// reads a byte into result[*index] and increments index
+boolean PubSubClient::readByte(uint8_t * result, uint16_t * index){
+  uint16_t current_index = *index;
+  uint8_t * write_address = &(result[current_index]);
+  if(readByte(write_address)){
+    *index = current_index + 1;
+    return true;
+  }
+  return false;
+}
+
+uint16_t PubSubClient::readPacket(uint8_t* lengthLength) {
+    uint16_t len = 0;
+    if(!readByte(buffer, &len)) return 0;
+    bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH;
+    uint32_t multiplier = 1;
+    uint16_t length = 0;
+    uint8_t digit = 0;
+    uint16_t skip = 0;
+    uint8_t start = 0;
+
+    do {
+        if (len == 5) {
+            // Invalid remaining length encoding - kill the connection
+            _state = MQTT_DISCONNECTED;
+            _client->stop();
+            return 0;
+        }
+        if(!readByte(&digit)) return 0;
+        buffer[len++] = digit;
+        length += (digit & 127) * multiplier;
+        multiplier *= 128;
+    } while ((digit & 128) != 0);
+    *lengthLength = len-1;
+
+    if (isPublish) {
+        // Read in topic length to calculate bytes to skip over for Stream writing
+        if(!readByte(buffer, &len)) return 0;
+        if(!readByte(buffer, &len)) return 0;
+        skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2];
+        start = 2;
+        if (buffer[0]&MQTTQOS1) {
+            // skip message id
+            skip += 2;
+        }
+    }
+
+    for (uint16_t i = start;i<length;i++) {
+        if(!readByte(&digit)) return 0;
+        if (this->stream) {
+            if (isPublish && len-*lengthLength-2>skip) {
+                this->stream->write(digit);
+            }
+        }
+        if (len < MQTT_MAX_PACKET_SIZE) {
+            buffer[len] = digit;
+        }
+        len++;
+    }
+
+    if (!this->stream && len > MQTT_MAX_PACKET_SIZE) {
+        len = 0; // This will cause the packet to be ignored.
+    }
+
+    return len;
+}
+
+boolean PubSubClient::loop() {
+    if (connected()) {
+        unsigned long t = millis();
+        if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) {
+            if (pingOutstanding) {
+                this->_state = MQTT_CONNECTION_TIMEOUT;
+                _client->stop();
+                return false;
+            } else {
+                buffer[0] = MQTTPINGREQ;
+                buffer[1] = 0;
+                _client->write(buffer,2);
+                lastOutActivity = t;
+                lastInActivity = t;
+                pingOutstanding = true;
+            }
+        }
+        if (_client->available()) {
+            uint8_t llen;
+            uint16_t len = readPacket(&llen);
+            uint16_t msgId = 0;
+            uint8_t *payload;
+            if (len > 0) {
+                lastInActivity = t;
+                uint8_t type = buffer[0]&0xF0;
+                if (type == MQTTPUBLISH) {
+                    if (callback) {
+                        uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; /* topic length in bytes */
+                        memmove(buffer+llen+2,buffer+llen+3,tl); /* move topic inside buffer 1 byte to front */
+                        buffer[llen+2+tl] = 0; /* end the topic as a 'C' string with \x00 */
+                        char *topic = (char*) buffer+llen+2;
+                        // msgId only present for QOS>0
+                        if ((buffer[0]&0x06) == MQTTQOS1) {
+                            msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1];
+                            payload = buffer+llen+3+tl+2;
+                            callback(topic,payload,len-llen-3-tl-2);
+
+                            buffer[0] = MQTTPUBACK;
+                            buffer[1] = 2;
+                            buffer[2] = (msgId >> 8);
+                            buffer[3] = (msgId & 0xFF);
+                            _client->write(buffer,4);
+                            lastOutActivity = t;
+
+                        } else {
+                            payload = buffer+llen+3+tl;
+                            callback(topic,payload,len-llen-3-tl);
+                        }
+                    }
+                } else if (type == MQTTPINGREQ) {
+                    buffer[0] = MQTTPINGRESP;
+                    buffer[1] = 0;
+                    _client->write(buffer,2);
+                } else if (type == MQTTPINGRESP) {
+                    pingOutstanding = false;
+                }
+            } else if (!connected()) {
+                // readPacket has closed the connection
+                return false;
+            }
+        }
+        return true;
+    }
+    return false;
+}
+
+boolean PubSubClient::publish(const char* topic, const char* payload) {
+    return publish(topic,(const uint8_t*)payload,strlen(payload),false);
+}
+
+boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained) {
+    return publish(topic,(const uint8_t*)payload,strlen(payload),retained);
+}
+
+boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength) {
+    return publish(topic, payload, plength, false);
+}
+
+boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) {
+    if (connected()) {
+        if (MQTT_MAX_PACKET_SIZE < MQTT_MAX_HEADER_SIZE + 2+strlen(topic) + plength) {
+            // Too long
+            return false;
+        }
+        // Leave room in the buffer for header and variable length field
+        uint16_t length = MQTT_MAX_HEADER_SIZE;
+        length = writeString(topic,buffer,length);
+        uint16_t i;
+        for (i=0;i<plength;i++) {
+            buffer[length++] = payload[i];
+        }
+        uint8_t header = MQTTPUBLISH;
+        if (retained) {
+            header |= 1;
+        }
+        return write(header,buffer,length-MQTT_MAX_HEADER_SIZE);
+    }
+    return false;
+}
+
+boolean PubSubClient::publish_P(const char* topic, const char* payload, boolean retained) {
+    return publish_P(topic, (const uint8_t*)payload, strlen(payload), retained);
+}
+
+boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) {
+    uint8_t llen = 0;
+    uint8_t digit;
+    unsigned int rc = 0;
+    uint16_t tlen;
+    unsigned int pos = 0;
+    unsigned int i;
+    uint8_t header;
+    unsigned int len;
+
+    if (!connected()) {
+        return false;
+    }
+
+    tlen = strlen(topic);
+
+    header = MQTTPUBLISH;
+    if (retained) {
+        header |= 1;
+    }
+    buffer[pos++] = header;
+    len = plength + 2 + tlen;
+    do {
+        digit = len % 128;
+        len = len / 128;
+        if (len > 0) {
+            digit |= 0x80;
+        }
+        buffer[pos++] = digit;
+        llen++;
+    } while(len>0);
+
+    pos = writeString(topic,buffer,pos);
+
+    rc += _client->write(buffer,pos);
+
+    for (i=0;i<plength;i++) {
+        rc += _client->write((char)pgm_read_byte_near(payload + i));
+    }
+
+    lastOutActivity = millis();
+
+    return rc == tlen + 4 + plength;
+}
+
+boolean PubSubClient::beginPublish(const char* topic, unsigned int plength, boolean retained) {
+    if (connected()) {
+        // Send the header and variable length field
+        uint16_t length = MQTT_MAX_HEADER_SIZE;
+        length = writeString(topic,buffer,length);
+        uint16_t i;
+        uint8_t header = MQTTPUBLISH;
+        if (retained) {
+            header |= 1;
+        }
+        size_t hlen = buildHeader(header, buffer, plength+length-MQTT_MAX_HEADER_SIZE);
+        uint16_t rc = _client->write(buffer+(MQTT_MAX_HEADER_SIZE-hlen),length-(MQTT_MAX_HEADER_SIZE-hlen));
+        lastOutActivity = millis();
+        return (rc == (length-(MQTT_MAX_HEADER_SIZE-hlen)));
+    }
+    return false;
+}
+
+int PubSubClient::endPublish() {
+ return 1;
+}
+
+size_t PubSubClient::write(uint8_t data) {
+    lastOutActivity = millis();
+    return _client->write(data);
+}
+
+size_t PubSubClient::write(const uint8_t *buffer, size_t size) {
+    lastOutActivity = millis();
+    return _client->write(buffer,size);
+}
+
+size_t PubSubClient::buildHeader(uint8_t header, uint8_t* buf, uint16_t length) {
+    uint8_t lenBuf[4];
+    uint8_t llen = 0;
+    uint8_t digit;
+    uint8_t pos = 0;
+    uint16_t len = length;
+    do {
+        digit = len % 128;
+        len = len / 128;
+        if (len > 0) {
+            digit |= 0x80;
+        }
+        lenBuf[pos++] = digit;
+        llen++;
+    } while(len>0);
+
+    buf[4-llen] = header;
+    for (int i=0;i<llen;i++) {
+        buf[MQTT_MAX_HEADER_SIZE-llen+i] = lenBuf[i];
+    }
+    return llen+1; // Full header size is variable length bit plus the 1-byte fixed header
+}
+
+boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) {
+    uint16_t rc;
+    uint8_t hlen = buildHeader(header, buf, length);
+
+#ifdef MQTT_MAX_TRANSFER_SIZE
+    uint8_t* writeBuf = buf+(MQTT_MAX_HEADER_SIZE-hlen);
+    uint16_t bytesRemaining = length+hlen;  //Match the length type
+    uint8_t bytesToWrite;
+    boolean result = true;
+    while((bytesRemaining > 0) && result) {
+        bytesToWrite = (bytesRemaining > MQTT_MAX_TRANSFER_SIZE)?MQTT_MAX_TRANSFER_SIZE:bytesRemaining;
+        rc = _client->write(writeBuf,bytesToWrite);
+        result = (rc == bytesToWrite);
+        bytesRemaining -= rc;
+        writeBuf += rc;
+    }
+    return result;
+#else
+    rc = _client->write(buf+(MQTT_MAX_HEADER_SIZE-hlen),length+hlen);
+    lastOutActivity = millis();
+    return (rc == hlen+length);
+#endif
+}
+
+boolean PubSubClient::subscribe(const char* topic) {
+    return subscribe(topic, 0);
+}
+
+boolean PubSubClient::subscribe(const char* topic, uint8_t qos) {
+    if (qos > 1) {
+        return false;
+    }
+    if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) {
+        // Too long
+        return false;
+    }
+    if (connected()) {
+        // Leave room in the buffer for header and variable length field
+        uint16_t length = MQTT_MAX_HEADER_SIZE;
+        nextMsgId++;
+        if (nextMsgId == 0) {
+            nextMsgId = 1;
+        }
+        buffer[length++] = (nextMsgId >> 8);
+        buffer[length++] = (nextMsgId & 0xFF);
+        length = writeString((char*)topic, buffer,length);
+        buffer[length++] = qos;
+        return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-MQTT_MAX_HEADER_SIZE);
+    }
+    return false;
+}
+
+boolean PubSubClient::unsubscribe(const char* topic) {
+    if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) {
+        // Too long
+        return false;
+    }
+    if (connected()) {
+        uint16_t length = MQTT_MAX_HEADER_SIZE;
+        nextMsgId++;
+        if (nextMsgId == 0) {
+            nextMsgId = 1;
+        }
+        buffer[length++] = (nextMsgId >> 8);
+        buffer[length++] = (nextMsgId & 0xFF);
+        length = writeString(topic, buffer,length);
+        return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-MQTT_MAX_HEADER_SIZE);
+    }
+    return false;
+}
+
+void PubSubClient::disconnect() {
+    buffer[0] = MQTTDISCONNECT;
+    buffer[1] = 0;
+    _client->write(buffer,2);
+    _state = MQTT_DISCONNECTED;
+    _client->flush();
+    _client->stop();
+    lastInActivity = lastOutActivity = millis();
+}
+
+uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t pos) {
+    const char* idp = string;
+    uint16_t i = 0;
+    pos += 2;
+    while (*idp) {
+        buf[pos++] = *idp++;
+        i++;
+    }
+    buf[pos-i-2] = (i >> 8);
+    buf[pos-i-1] = (i & 0xFF);
+    return pos;
+}
+
+
+boolean PubSubClient::connected() {
+    boolean rc;
+    if (_client == NULL ) {
+        rc = false;
+    } else {
+        rc = (int)_client->connected();
+        if (!rc) {
+            if (this->_state == MQTT_CONNECTED) {
+                this->_state = MQTT_CONNECTION_LOST;
+                _client->flush();
+                _client->stop();
+            }
+        }
+    }
+    return rc;
+}
+
+PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) {
+    IPAddress addr(ip[0],ip[1],ip[2],ip[3]);
+    return setServer(addr,port);
+}
+
+PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) {
+    this->ip = ip;
+    this->port = port;
+    this->domain = NULL;
+    return *this;
+}
+
+PubSubClient& PubSubClient::setServer(const char * domain, uint16_t port) {
+    this->domain = domain;
+    this->port = port;
+    return *this;
+}
+
+PubSubClient& PubSubClient::setCallback(MQTT_CALLBACK_SIGNATURE) {
+    this->callback = callback;
+    return *this;
+}
+
+PubSubClient& PubSubClient::setClient(Client& client){
+    this->_client = &client;
+    return *this;
+}
+
+PubSubClient& PubSubClient::setStream(Stream& stream){
+    this->stream = &stream;
+    return *this;
+}
+
+int PubSubClient::state() {
+    return this->_state;
+}
diff --git a/wetterstation/PubSubClient.h b/wetterstation/PubSubClient.h
new file mode 100644
index 0000000000000000000000000000000000000000..cb7a36d6df6dac38e087d574c5c5c313078fd74b
--- /dev/null
+++ b/wetterstation/PubSubClient.h
@@ -0,0 +1,173 @@
+/*
+ PubSubClient.h - A simple client for MQTT.
+  Nick O'Leary
+  http://knolleary.net
+*/
+
+#ifndef PubSubClient_h
+#define PubSubClient_h
+
+#include <Arduino.h>
+#include "IPAddress.h"
+#include "Client.h"
+#include "Stream.h"
+
+#define MQTT_VERSION_3_1      3
+#define MQTT_VERSION_3_1_1    4
+
+// MQTT_VERSION : Pick the version
+//#define MQTT_VERSION MQTT_VERSION_3_1
+#ifndef MQTT_VERSION
+#define MQTT_VERSION MQTT_VERSION_3_1_1
+#endif
+
+// MQTT_MAX_PACKET_SIZE : Maximum packet size
+#ifndef MQTT_MAX_PACKET_SIZE
+#define MQTT_MAX_PACKET_SIZE 1024
+#endif
+
+// MQTT_KEEPALIVE : keepAlive interval in Seconds
+#ifndef MQTT_KEEPALIVE
+#define MQTT_KEEPALIVE 15
+#endif
+
+// MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds
+#ifndef MQTT_SOCKET_TIMEOUT
+#define MQTT_SOCKET_TIMEOUT 15
+#endif
+
+// MQTT_MAX_TRANSFER_SIZE : limit how much data is passed to the network client
+//  in each write call. Needed for the Arduino Wifi Shield. Leave undefined to
+//  pass the entire MQTT packet in each write call.
+//#define MQTT_MAX_TRANSFER_SIZE 80
+
+// Possible values for client.state()
+#define MQTT_CONNECTION_TIMEOUT     -4
+#define MQTT_CONNECTION_LOST        -3
+#define MQTT_CONNECT_FAILED         -2
+#define MQTT_DISCONNECTED           -1
+#define MQTT_CONNECTED               0
+#define MQTT_CONNECT_BAD_PROTOCOL    1
+#define MQTT_CONNECT_BAD_CLIENT_ID   2
+#define MQTT_CONNECT_UNAVAILABLE     3
+#define MQTT_CONNECT_BAD_CREDENTIALS 4
+#define MQTT_CONNECT_UNAUTHORIZED    5
+
+#define MQTTCONNECT     1 << 4  // Client request to connect to Server
+#define MQTTCONNACK     2 << 4  // Connect Acknowledgment
+#define MQTTPUBLISH     3 << 4  // Publish message
+#define MQTTPUBACK      4 << 4  // Publish Acknowledgment
+#define MQTTPUBREC      5 << 4  // Publish Received (assured delivery part 1)
+#define MQTTPUBREL      6 << 4  // Publish Release (assured delivery part 2)
+#define MQTTPUBCOMP     7 << 4  // Publish Complete (assured delivery part 3)
+#define MQTTSUBSCRIBE   8 << 4  // Client Subscribe request
+#define MQTTSUBACK      9 << 4  // Subscribe Acknowledgment
+#define MQTTUNSUBSCRIBE 10 << 4 // Client Unsubscribe request
+#define MQTTUNSUBACK    11 << 4 // Unsubscribe Acknowledgment
+#define MQTTPINGREQ     12 << 4 // PING Request
+#define MQTTPINGRESP    13 << 4 // PING Response
+#define MQTTDISCONNECT  14 << 4 // Client is Disconnecting
+#define MQTTReserved    15 << 4 // Reserved
+
+#define MQTTQOS0        (0 << 1)
+#define MQTTQOS1        (1 << 1)
+#define MQTTQOS2        (2 << 1)
+
+// Maximum size of fixed header and variable length size header
+#define MQTT_MAX_HEADER_SIZE 5
+
+#if defined(ESP8266) || defined(ESP32)
+#include <functional>
+#define MQTT_CALLBACK_SIGNATURE std::function<void(char*, uint8_t*, unsigned int)> callback
+#else
+#define MQTT_CALLBACK_SIGNATURE void (*callback)(char*, uint8_t*, unsigned int)
+#endif
+
+#define CHECK_STRING_LENGTH(l,s) if (l+2+strlen(s) > MQTT_MAX_PACKET_SIZE) {_client->stop();return false;}
+
+class PubSubClient : public Print {
+private:
+   Client* _client;
+   uint8_t buffer[MQTT_MAX_PACKET_SIZE];
+   uint16_t nextMsgId;
+   unsigned long lastOutActivity;
+   unsigned long lastInActivity;
+   bool pingOutstanding;
+   MQTT_CALLBACK_SIGNATURE;
+   uint16_t readPacket(uint8_t*);
+   boolean readByte(uint8_t * result);
+   boolean readByte(uint8_t * result, uint16_t * index);
+   boolean write(uint8_t header, uint8_t* buf, uint16_t length);
+   uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos);
+   // Build up the header ready to send
+   // Returns the size of the header
+   // Note: the header is built at the end of the first MQTT_MAX_HEADER_SIZE bytes, so will start
+   //       (MQTT_MAX_HEADER_SIZE - <returned size>) bytes into the buffer
+   size_t buildHeader(uint8_t header, uint8_t* buf, uint16_t length);
+   IPAddress ip;
+   const char* domain;
+   uint16_t port;
+   Stream* stream;
+   int _state;
+public:
+   PubSubClient();
+   PubSubClient(Client& client);
+   PubSubClient(IPAddress, uint16_t, Client& client);
+   PubSubClient(IPAddress, uint16_t, Client& client, Stream&);
+   PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client);
+   PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&);
+   PubSubClient(uint8_t *, uint16_t, Client& client);
+   PubSubClient(uint8_t *, uint16_t, Client& client, Stream&);
+   PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client);
+   PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&);
+   PubSubClient(const char*, uint16_t, Client& client);
+   PubSubClient(const char*, uint16_t, Client& client, Stream&);
+   PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client);
+   PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&);
+
+   PubSubClient& setServer(IPAddress ip, uint16_t port);
+   PubSubClient& setServer(uint8_t * ip, uint16_t port);
+   PubSubClient& setServer(const char * domain, uint16_t port);
+   PubSubClient& setCallback(MQTT_CALLBACK_SIGNATURE);
+   PubSubClient& setClient(Client& client);
+   PubSubClient& setStream(Stream& stream);
+
+   boolean connect(const char* id);
+   boolean connect(const char* id, const char* user, const char* pass);
+   boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage);
+   boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage);
+   boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession);
+   void disconnect();
+   boolean publish(const char* topic, const char* payload);
+   boolean publish(const char* topic, const char* payload, boolean retained);
+   boolean publish(const char* topic, const uint8_t * payload, unsigned int plength);
+   boolean publish(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained);
+   boolean publish_P(const char* topic, const char* payload, boolean retained);
+   boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained);
+   // Start to publish a message.
+   // This API:
+   //   beginPublish(...)
+   //   one or more calls to write(...)
+   //   endPublish()
+   // Allows for arbitrarily large payloads to be sent without them having to be copied into
+   // a new buffer and held in memory at one time
+   // Returns 1 if the message was started successfully, 0 if there was an error
+   boolean beginPublish(const char* topic, unsigned int plength, boolean retained);
+   // Finish off this publish message (started with beginPublish)
+   // Returns 1 if the packet was sent successfully, 0 if there was an error
+   int endPublish();
+   // Write a single byte of payload (only to be used with beginPublish/endPublish)
+   virtual size_t write(uint8_t);
+   // Write size bytes from buffer into the payload (only to be used with beginPublish/endPublish)
+   // Returns the number of bytes written
+   virtual size_t write(const uint8_t *buffer, size_t size);
+   boolean subscribe(const char* topic);
+   boolean subscribe(const char* topic, uint8_t qos);
+   boolean unsubscribe(const char* topic);
+   boolean loop();
+   boolean connected();
+   int state();
+};
+
+
+#endif
diff --git a/wetterstation/settings.h b/wetterstation/settings.h
new file mode 100644
index 0000000000000000000000000000000000000000..5200d5f707e0a02bc824dd831654d1a4a75a482d
--- /dev/null
+++ b/wetterstation/settings.h
@@ -0,0 +1,49 @@
+//
+// settings for WiFi connection
+//
+char * ssid     = "Sensors";                          // WiFi SSID
+char * password = "mySensorNetz";                     // WiFi password
+
+//
+// MQTT Server
+//
+String frontendId = String(ESP.getChipId());          // Set chipId as frontendId
+const char* mqttHost = "MQTT_HOST";                   // Adresse des MQTT Servers
+const char* mqttUser = "MQTT_USER";                   // MQTT Username
+const char* mqttPass = "MQTT_PASS";                   // MQTT Password
+int mqttPort = 1883;                                  // 1883 - Ist der Standard TCP Port
+
+//
+// MQTT Topics to subscribe
+//
+const char* mqttTopic = String("/wetterstation/frontend/" + frontendId + "/weather").c_str();
+const char* mqttTopicBackend = "/wetterstation/backend/settings";
+
+//
+// Settings for Backend
+//
+String backendPlz = "YOUT_PLZ";
+String backendLngCode = "YOUT_LANDUAGE_CODE";
+String backendCity = "YOUR_CITY";
+
+//
+// settings
+//
+int startupDelay = 1000;                              // startup delay
+int loopDelay = 1000;                                 // main loop delay between sensor updates
+
+int maxForecastLoop = 10;                             // number of main loops before the forecast is refreshed, looping through all cities
+int weatherForecastLoop = 0;
+int weatherForecastLoopInc = 1;
+
+int displayStartupDimValue = 30;                      // startup display backlight level
+int displayDimValue = 150;                            // main display backlight level
+int displayDimStep = 1;                               // dim step
+int dimStartupDelay = 5;                              // delay for fading in
+int dimPageDelay = 0;                                 // delay for fading between pages
+
+const char* ntpServerName = "de.pool.ntp.org";        // server pool
+const long timeZoneoffsetGMT = 3600;                  // offset from Greenwich Meridan Time
+boolean DST = false;                                  // daylight saving time
+int timeServerDelay = 1000;                           // delay for the time server to reply
+int timeServerRefreshDelay = 3600;
diff --git a/wetterstation/wetterstation.ino b/wetterstation/wetterstation.ino
index 85d42c83b2f34ac016ff8f839a3fa3daf0c9572e..a3e3ed18498a4d7170d78c89852494fb0ed52b19 100644
--- a/wetterstation/wetterstation.ino
+++ b/wetterstation/wetterstation.ino
@@ -15,7 +15,6 @@
 
   contact: dev@itstall.de
 **********************************************************************/
-
 //#define DEBUG
 #define DEBUG_NO_PAGE_FADE
 #define DEBUG_NO_TOUCH
@@ -27,100 +26,39 @@
 #include <Wire.h>
 #include <SPI.h>                                // I2C library
 #include <ArduinoJson.h>                        // https://github.com/bblanchon/ArduinoJson
+#include <NTPClient.h>
 #include <ESP8266WiFi.h>                        // WiFi library
 #include <WiFiUdp.h>                            // Udp library
 #include <TimeLib.h>                            // Time library
+#include "PubSubClient.h"                       // http://knolleary.net/arduino-client-for-mqtt/
+#include "settings.h"
 
 extern "C" {
   #include "user_interface.h"
 }
 
-//
-// settings for WiFi connection
-//
-char * ssid     = "";                    // WiFi SSID
-char * password = "";               // WiFi password
-
 unsigned int localPort = 2390;                  // local port to listen for UDP packets
 IPAddress timeServerIP;                         // IP address of random server
-const char* ntpServerName = "de.pool.ntp.org";  // server pool
+IPAddress mqttHostIP;                           // IP address of random server
 byte packetBuffer[48];                          // buffer to hold incoming and outgoing packets
-int timeZoneoffsetGMT = 3600;                   // offset from Greenwich Meridan Time
-boolean DST = false;                            // daylight saving time
-WiFiUDP clockUDP;                               // initialize a UDP instance
-
-//
-// settings for the openweathermap connection
-// sign up, get your api key and insert it below
-//
-char * servername = "api.openweathermap.org";         // remote server with weather info
-String APIKEY = "45f6ce019087f08b45d73872319c0573";   // personal api key for retrieving the weather data
-
-const int httpPort = 80;
-String result;
-int cityIDLoop = 0;
-
-// a list of cities you want to display the forecast for
-// get the ID at https://openweathermap.org/
-// type the city, click search and click on the town
-// then check the link, like this: https://openweathermap.org/city/5128581
-// 5128581 is the ID for New York
-String cityIDs[] = {
-  "2836455",  // Schonungen
-  ""          // end the list with an empty string
-};
-
-//
-// settings
-//
-int startupDelay = 1000;                      // startup delay
-int loopDelay = 3000;                         // main loop delay between sensor updates
-
-int timeServerDelay = 1000;                   // delay for the time server to reply
-int timeServerPasses = 4;                     // number of tries to connect to the time server before timing out
-int timeServerResyncNumOfLoops = 3000;        // number of loops before refreshing the time. one loop takes approx. 28 seconds
-int timeServerResyncNumOfLoopsCounter = 0;
-boolean timeServerConnected = false;          // is set to true when the time is read from the server
-
-int maxForecastLoop = 10;                     // number of main loops before the forecast is refreshed, looping through all cities
-int weatherForecastLoop = 0;
-int weatherForecastLoopInc = 1;
-
-int displayStartupDimValue = 30;              // startup display backlight level
-int displayDimValue = 150;                    // main display backlight level
-int displayDimStep = 1;                       // dim step
-int dimStartupDelay = 50;                     // delay for fading in
-int dimPageDelay = 0;                         // delay for fading between pages
 
 //
 // initialize variables
 //
 int page = 0;
-
-float bmeAltitude = 0;
-float bmeHumidity = 0;
-float bmePressure = 0;
-float bmeTemperature = 0;
-
 String command;
 String doubleQuote = "\"\"";
 
-//
-// initialize timer
-//
-os_timer_t secTimer;
-
-void timerDisplayTime(void *pArg) {
-  displayTime();
-}
+WiFiClient wifiClient;
+WiFiUDP ntpUDP;
+NTPClient timeClient(ntpUDP, ntpServerName, timeZoneoffsetGMT, timeServerRefreshDelay);
+PubSubClient mqttClient(wifiClient);
 
-//
-// setup
-//
 void setup() {
-#ifdef DEBUG
+//#ifdef DEBUG
   Serial.begin(9600);
-#endif
+  Serial.println("setup...");
+//#endif
 
   nexSerial.begin(9600);
 
@@ -130,53 +68,28 @@ void setup() {
 
   delay(startupDelay);
 
-  displayFadeIn(0, displayStartupDimValue, dimStartupDelay);
+  displayFadeIn(1, displayStartupDimValue, dimStartupDelay);
 
-  connectToWifi();
-  clockUDP.begin(localPort);
+  reconnectToWifi();
+  timeClient.begin();
   getTimeFromServer();
 
-  if (timeServerConnected) {
-    displayTime();
-  }
-
-  displayDate();
-
-  os_timer_setfn(&secTimer, timerDisplayTime, NULL);
-  if (timeServerConnected) {
-    os_timer_arm(&secTimer, 1000, true);
-  }
-
   displayFadeIn(displayStartupDimValue, displayDimValue, dimStartupDelay / 2);
 
-#ifdef DEBUG
-  Serial.println("Starting main loop");
-#endif
+  mqttClient.setServer(mqttHost, mqttPort);
+  mqttClient.setCallback(getWeatherDataMqtt);
+  reconnectMqtt();
 }
-
-//
-// main loop
-//
 void loop() {
-  if (!timeServerConnected) {
-    getTimeFromServer();
-    if (timeServerConnected)
-      os_timer_arm(&secTimer, 1000, true);
-  }
+#ifdef DEBUG
+  Serial.println("loop");
+#endif
 
   if (page == 0) {
 
     if (weatherForecastLoop == maxForecastLoop) {
-      timeServerResyncNumOfLoopsCounter += 1;
-      if (timeServerResyncNumOfLoopsCounter == timeServerResyncNumOfLoops) {
-        getTimeFromServer();
-        timeServerResyncNumOfLoopsCounter = 0;
-      }
-
       page = 1;
-      getWeatherData();
       weatherForecastLoopInc = -weatherForecastLoopInc;
-      displayDate();
     }
 
     delayCheckTouch(loopDelay);
@@ -197,9 +110,6 @@ void loop() {
 #endif
 
       weatherForecastLoopInc = -weatherForecastLoopInc;
-
-      displayTime();
-      displayDate();
     }
     else
       delayCheckTouch(loopDelay);
@@ -207,45 +117,30 @@ void loop() {
 
   weatherForecastLoop += weatherForecastLoopInc;
 
-#ifdef DEBUG
-  Serial.print(page);
-  Serial.print(" ");
-  Serial.print(weatherForecastLoop);
-  Serial.print(" ");
-  Serial.print(timeServerResyncNumOfLoopsCounter);
-  Serial.print(" ");
-  Serial.print(timeServerResyncNumOfLoops);
-  Serial.println("");
-#endif
-}
-
-void displayDate() {
-  time_t t = now();
+  // Update date and time on display
+  sendToLCD(1, "time", String(timeClient.getFormattedTime()));
+  sendToLCD(1, "date", dayAsString(timeClient.getDay()));
 
-  command = "date.txt=\"" + String(day(t)) + " " + monthAsString(month(t)) + "\"";
-  printNextionCommand(command);
-  command = "year.txt=\"" + String(year(t)) + "\"";
-  printNextionCommand(command);
-}
+  reconnectToWifi();
 
-void displayTime() {
-  time_t t = now();
-  char timeString[9];
+  reconnectMqtt();
+  mqttClient.loop();
 
-  snprintf(timeString, sizeof(timeString), "%02d:%02d:%02d", hour(t), minute(t), second(t));
-  command = "time.txt=\"" + String(timeString) + "\"";
-  printNextionCommand(command);
+#ifdef DEBUG
+    Serial.print(page);
+    Serial.print(" ");
+    Serial.print(weatherForecastLoop);
+    Serial.println("");
+#endif
 }
-
-//
-// Nextion commands
-//
 void printNextionCommand (String command) {
   nexSerial.print(command);
   endNextionCommand();
 }
-
 void sendToLCD(uint8_t type, String index, String cmd) {
+#ifdef DEBUG
+  Serial.println("sendToLCD");
+#endif
   if (type == 1 ) {
     nexSerial.print(index);
     nexSerial.print(".txt=");
@@ -270,14 +165,15 @@ void sendToLCD(uint8_t type, String index, String cmd) {
 
   endNextionCommand();
 }
-
 void endNextionCommand() {
   nexSerial.write(0xff);
   nexSerial.write(0xff);
   nexSerial.write(0xff);
 }
-
 void displayFadeIn(int fromValue, int toValue, int fadeDelay) {
+#ifdef DEBUG
+  Serial.println("displayFadeIn");
+#endif
   for (int i = fromValue; i <= toValue; i += displayDimStep) {
     if (i > toValue) {
       i = toValue;
@@ -286,8 +182,10 @@ void displayFadeIn(int fromValue, int toValue, int fadeDelay) {
     delay(fadeDelay);
   }
 }
-
 void displayFadeOut(int fromValue, int fadeDelay) {
+#ifdef DEBUG
+  Serial.println("displayFadeOut");
+#endif
   for (int i = fromValue; i >= 0; i -= displayDimStep) {
     if (i < 0) {
       i = 0;
@@ -296,174 +194,101 @@ void displayFadeOut(int fromValue, int fadeDelay) {
     delay(fadeDelay);
   }
 }
-
-//
-// network functions
-//
-void connectToWifi() {
-  int wifiBlink = 0;
-
-  //  WiFi.enableSTA(true);
-  WiFi.mode(WIFI_STA);
-  WiFi.disconnect();
-
-  WiFi.begin(ssid, password);
-
-  while (WiFi.status() != WL_CONNECTED) {
-    if (wifiBlink == 0) {
-      printNextionCommand("wifi_connect.txt=\"connect...\"");
-      wifiBlink = 1;
-    }
-    else {
-      printNextionCommand("wifi_connect.txt=" + doubleQuote);
-      wifiBlink = 0;
+void reconnectToWifi() {
+#ifdef DEBUG
+  Serial.println("reconnectToWifi...");
+#endif
+  if(WiFi.status() != WL_CONNECTED) {
+    int wifiBlink = 0;
+  
+    //  WiFi.enableSTA(true);
+    WiFi.mode(WIFI_STA);
+    WiFi.disconnect();
+    WiFi.begin(ssid, password);
+  
+    while (WiFi.status() != WL_CONNECTED) {
+      if (wifiBlink == 0) {
+        printNextionCommand("wifi_connect.txt=\"connect...\"");
+        sendToLCD(1, "txtIp", "\"No IP yet...\"");
+        wifiBlink = 1;
+      }
+      else {
+        printNextionCommand("wifi_connect.txt=" + doubleQuote);
+        wifiBlink = 0;
+      }
+      delay(500);
     }
-    delay(500);
   }
+#ifdef DEBUG
+    Serial.print("Wifi IP Address: ");
+    Serial.println(WiFi.localIP().toString());
+#endif
+  sendToLCD(1, "txtIp", WiFi.localIP().toString());
 
   printNextionCommand("wifi_connect.txt=" + doubleQuote);
 }
-
 void getTimeFromServer() {
 #ifdef DEBUG
-  Serial.print("Getting time from server...");
-#endif
-
-  int connectStatus = 0, i = 0;
-  unsigned long unixTime;
-
-  while (i < timeServerPasses && !connectStatus) {
-#ifdef DEBUG
-    Serial.print(i);
-    Serial.print("...");
+  Serial.println("getTimeFromServer");
 #endif
 
-    printNextionCommand("time.txt=\"get time..\"");
-    WiFi.hostByName(ntpServerName, timeServerIP);
-    sendNTPpacket(timeServerIP);
-    delay(timeServerDelay / 2);
-    connectStatus = clockUDP.parsePacket();
-    printNextionCommand("time.txt=" + doubleQuote);
-    delay(timeServerDelay / 2);
-    i++;
+  sendToLCD(1, "time", "get time..");
+  while(!timeClient.update()) {
+    timeClient.forceUpdate();
   }
-
-  if (connectStatus) {
+  timeClient.setTimeOffset(timeZoneoffsetGMT);
+  timeClient.setUpdateInterval(timeServerRefreshDelay);
+}
+void reconnectMqtt() {
+  String settings;
+  StaticJsonDocument<1024> doc;
+  JsonObject object = doc.to<JsonObject>();
+  object["plz"] = backendPlz;
+  object["lngCode"] = backendLngCode;
+  object["frontendId"] = frontendId;
+  serializeJson(doc, settings);
+
+  while (!mqttClient.connected()) {
+    if (mqttClient.connect(frontendId.c_str(), mqttUser, mqttPass)) {
+      Serial.println("MQTT Connected");
+      //mqttClient.subscribe(mqttTopic);
+      mqttClient.subscribe("/wetterstation/frontend/7363421/weather");
+      Serial.print("MQTT Subscribe to: ");
+      Serial.println(mqttTopic);
+      mqttClient.publish(mqttTopicBackend, settings.c_str());
+    }
+    else {
 #ifdef DEBUG
-    Serial.print(i);
-    Serial.println("...connected");
+      Serial.print("failed, rc=");
+      Serial.print(mqttClient.state());
+      Serial.println(" retrying in 5 seconds");
 #endif
-
-    timeServerConnected = true;
-    clockUDP.read(packetBuffer, 48);
-
-    // the timestamp starts at byte 40 of the received packet and is four bytes, or two words, long.
-    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
-    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
-    // the timestamp is in seconds from 1900, add 70 years to get Unixtime
-    unixTime = (highWord << 16 | lowWord) - 2208988800 + timeZoneoffsetGMT;
-
-    if (DST) {
-      unixTime = unixTime + 3600;
+      delay(5000);
     }
-
-    setTime(unixTime);
   }
-  else {
+}
+void getWeatherDataMqtt(char* topic, byte* payload, unsigned int length) {
 #ifdef DEBUG
-    Serial.print(i);
-    Serial.println("...failed...");
+  Serial.println("getWeatherDataMqtt...");
+  Serial.println("From mqttTopic: " + String(mqttTopic));
+  Serial.println("From topic: " + String(topic));
 #endif
-
-    printNextionCommand("time.txt=\"failed....\"");
-    delay(timeServerDelay);
-    printNextionCommand("time.txt=" + doubleQuote);
-  }
-}
-
-unsigned long sendNTPpacket(IPAddress& address) {
-  memset(packetBuffer, 0, 48);
-  packetBuffer[0] = 0b11100011;     // LI, Version, Mode
-  packetBuffer[1] = 0;              // Stratum, or type of clock
-  packetBuffer[2] = 6;              // Polling Interval
-  packetBuffer[3] = 0xEC;           // Peer Clock Precision
-  // 8 bytes of zero for Root Delay & Root Dispersion
-  packetBuffer[12]  = 49;
-  packetBuffer[13]  = 0x4E;
-  packetBuffer[14]  = 49;
-  packetBuffer[15]  = 52;
-
-  clockUDP.beginPacket(address, 123);    //NTP requests are to port 123
-  clockUDP.write(packetBuffer, 48);
-  clockUDP.endPacket();
-}
-
-//
-// get and display weather data
-//
-void getWeatherData() { //client function to send/receive GET request data.
-  WiFiClient client;
-  if (!client.connect(servername, httpPort)) {
-    return;
-  }
-
-  String cityID = cityIDs[cityIDLoop];
-  cityIDLoop++;
-
-  if (cityIDs[cityIDLoop] == "") {
-    cityIDLoop = 0;
-  }
-
-  String url = "/data/2.5/forecast?id=" + cityID + "&units=metric&cnt=1&APPID=" + APIKEY + "&lang=de";
-  //String url = "/data/2.5/weather?id=" + cityID + "&units=metric&cnt=1&APPID=" + APIKEY;
-  //check weather properties at https://openweathermap.org/current
-
-  // This will send the request to the server
-  client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + servername + "\r\n" + "Connection: close\r\n\r\n");
-  unsigned long timeout = millis();
-  while (client.available() == 0) {
-    if (millis() - timeout > 5000) {
-      client.stop();
-      return;
-    }
-  }
-
-  result = "";
-  // Read all the lines of the reply from server
-  while (client.available()) {
-    result = client.readStringUntil('\r');
-  }
-
-  result.replace('[', ' ');
-  result.replace(']', ' ');
-
-  char jsonArray [result.length() + 1];
-  result.toCharArray(jsonArray, sizeof(jsonArray));
-  jsonArray[result.length() + 1] = '\0';
-
-  StaticJsonBuffer<1024> json_buf;
-  JsonObject& root = json_buf.parseObject(jsonArray);
-  if (!root.success()) {
-    nexSerial.println("parseObject() failed");
-  }
-
-  //check properties forecasts at https://openweathermap.org/forecast5
-
-  int weatherID = root["list"]["weather"]["id"];
-
-  String tmp0 = root["city"]["name"];
-  String tmp1 = root["list"]["weather"]["main"];
-  String tmp2 = root["list"]["weather"]["description"];
-  float  tmp3 = root["list"]["main"]["temp_min"];
-  float  tmp4 = root["list"]["main"]["temp_max"];
-  float  tmp5 = root["list"]["main"]["humidity"];
-  float  tmp6 = root["list"]["clouds"]["all"];
-  float  tmp7 = root["list"]["rain"]["3h"];
-  float  tmp8 = root["list"]["snow"]["3h"];
-  float  tmp9 = root["list"]["wind"]["speed"];
-  int    tmp10 = root["list"]["wind"]["deg"];
-  float  tmp11 = root["list"]["main"]["pressure"];
-  timeZoneoffsetGMT = root["city"]["timezone"];
+  // Parsing
+  StaticJsonDocument<1024> root;
+  deserializeJson(root, payload, length);
+
+  String tmp0 = backendCity;
+  //String tmp1 = root["main"];          // Icon main
+  //String tmp2 = root["description"];   // Icon description
+  float  tmp3 = root["tempMin"];
+  float  tmp4 = root["tempMax"];
+  float  tmp5 = root["humidity"];
+  float  tmp6 = root["clouds"];
+  float  tmp7 = root["rain3h"];
+  float  tmp8 = root["snow3h"];
+  float  tmp9 = root["windSpeed"];
+  int    tmp10 = root["windDeg"];
+  float  tmp11 = root["pressure"];
   //String tmp12 = root["list"]["dt_text"]; command = command + tmp12;
 
 #if !defined (DEBUG_NO_PAGE_FADE)
@@ -476,9 +301,9 @@ void getWeatherData() { //client function to send/receive GET request data.
   displayFadeIn(0, displayDimValue, dimPageDelay );
 #endif
 
-  setWeatherPicture(weatherID);
+  //setWeatherPicture(weatherID);
   sendToLCD(1, "city", tmp0);
-  sendToLCD(1, "description", tmp2);
+  //sendToLCD(1, "description", tmp2);
   sendToLCD(1, "humidity", String(tmp5, 0));
   sendToLCD(1, "rain", String(tmp7, 1));
   sendToLCD(1, "wind_dir", getShortWindDirection(tmp10));
@@ -488,8 +313,10 @@ void getWeatherData() { //client function to send/receive GET request data.
   sendToLCD(1, "temp_min", String(tmp3, 1));
   sendToLCD(1, "temp_max", String(tmp4, 1));
 }
-
 String getWindDirection (int degrees) {
+#ifdef DEBUG
+  Serial.println("getWindDirection...");
+#endif
   int sector = ((degrees + 11) / 22.5 - 1);
   switch (sector) {
     case 0: return "Nord";
@@ -510,8 +337,10 @@ String getWindDirection (int degrees) {
     case 15: return "Nord-Nordwest";
   }
 }
-
 String getShortWindDirection (int degrees) {
+#ifdef DEBUG
+  Serial.println("getShortWindDirection...");
+#endif
   int sector = ((degrees + 11) / 22.5 - 1);
   switch (sector) {
     case 0: return "N";
@@ -532,8 +361,10 @@ String getShortWindDirection (int degrees) {
     case 15: return "NNW";
   }
 }
-
 void setWeatherPicture(int weatherID) {
+#ifdef DEBUG
+  Serial.println("setWeatherPicture...");
+#endif
   switch (weatherID) {
     case 200:
     case 201:
@@ -598,29 +429,35 @@ void setWeatherPicture(int weatherID) {
     default: sendToLCD(3, "weatherpic", "10"); break; // dunno
   }
 }
-
 void delayCheckTouch (int delayTime) {
+#ifdef DEBUG
+  Serial.println("delayCheckTouch...");
+#endif
   unsigned long startMillis = millis();
 
   while (millis() - startMillis < delayTime) {
     delay(1000);
   }
 }
-
 String dayAsString(int day) {
+#ifdef DEBUG
+  Serial.println("dayAsString...");
+#endif
   switch (day) {
-    case 1: return "Sonntag";
-    case 2: return "Montag";
-    case 3: return "Dienstag";
-    case 4: return "Mittwoch";
-    case 5: return "Donnerstag";
-    case 6: return "Freitag";
-    case 7: return "Samstag";
+    case 1: return "Montag";
+    case 2: return "Dienstag";
+    case 3: return "Mittwoch";
+    case 4: return "Donnerstag";
+    case 5: return "Freitag";
+    case 6: return "Samstag";
+    case 7: return "Sonntag";
   }
   return "" ;
 }
-
 String monthAsString(int month) {
+#ifdef DEBUG
+  Serial.println("monthAsString...");
+#endif
   switch (month) {
     case 1:  return "Januar";
     case 2:  return "Februar";