diff --git a/.gitignore b/.gitignore
index 12a5de458818d9652e3110e932d4de0c3b6df64d..231fb3a0f8f145f92db50e3a9376090f92ec5dfa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
 didacticNet.h.gch
+.vscode
+.log
diff --git a/DownloadButton.png b/DownloadButton.png
new file mode 100644
index 0000000000000000000000000000000000000000..2f8a5b006a4935a43ebc0d8d075e6d66ac21d1ed
Binary files /dev/null and b/DownloadButton.png differ
diff --git a/README.md b/README.md
index 797b14dec96d3bf21dca892c72956899947f0343..50f583eee6fb565f9e2041b9ab73c6ba7d2e8397 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,243 @@
 # didacticNetwork
 
-Library for implementing networks on Arduino boards.
-The functionalities correspond to state of the art technologies, which are didactically reduced.
+Bibliothek zur Implementierung von vereinfachten Netzwerken auf Arduino-Boards.
+Die Funktionalitaeten entsprechen dem Stand der Technik, die Umsetzung ist didaktisch reduziert.
 
-## Supported so far:
-publish/subscribe network
+Für eine Nutzung der Bibliothek wird eine drahtlose Schnittstelle benoetigt, wleche sich an der Seriellen Schnittstelle betreiben lässt.
+Wir empfehlen unsere IR-Link-Module, die Sie selbst herstellen koennen (Schaltplan und Layout bei uns anfragen - Kontakt über [letsgoING.org](httsp://letsgoING.org) 
+oder z. B. hier erwerben koennen: [Hinweise zur Bestellung bei Aisler](#bestellung-bei-aisler).
 
-### usage
+
+## Download
+Start download with the button on the right side. Choose the right format and start the download.
+
+![](DownloadButton.png) 
+
+After download install library:
+https://www.arduino.cc/en/guide/libraries section "Importing a .zip Library"
+
+# publish/subscribe network
+
+## Beispiele
+
+**Broker:**
+- sPSN_Broker.ino        **->** Broker Applikation (muss nicht angepasst werden)
+
+**Clients:**
+- sPSN_Client1(2).ino    **->** Client Applikationen die sich gegenseitig einen analogen bzw. digtalen Wert senden
+- sPSN-ClientMinimal.ino **->** Minimal-Code für den einfachen Einstieg
+- sPSN-Chat.ino          **->** Chat-Applikation die Nachrichten unter eigenem Namen austauschen lässt
+
+## Funktionen und Parameter 
+
+### Client
+
+```cpp
+#Anlegen der Client-Instanz
+// Anlegen des didacticPSNetClient-Objekts
+// psnClient -> moeglicher Name für Objekt
+didacticPSNetClient psnClient;
+
+#Starten der Client-Instanz
+void psnClient.begin(Stream& sSerial, fcn clientCallback);
+// param1: Schnittstelle (Serial | SoftSerial)
+// param2: Callback-Funktion (Bezeichnung frei waehlbar)
+
+#Netzwerkverwaltung Client (Daten senden und Empfangen, Zugriffsregelung)
+bool psnClient.handleNetwork();
+// return: true wenn Daten versendet / false wenn nicht
+
+void psnClient.setInterval(long intervalTime);
+// param: Mindestwartezeit in ms zwischen zwei Sendevorgängen (default 500 ms)
+
+#Topic eines anderen Clients abbonieren
+int psnClient.subscribe(char* topic);
+// param: Topic String/char-Array ("example" / char topic[n])
+int psnClient.subscribe(char* topic, int length);
+// param1: Topic String/char-Array
+// param2: Anzahl Zeichen des Topics
+// return ERROR-Wert: DN_ERROR_NO_ERROR, 
+//                    DN_ERROR_TOPIC_LEN (Topic zu lang - wird abgeschnitten)
+
+#Topic eines anderen Clients entfernen
+bool psnClient.unsubscribe(char* topic);            
+// param: Topic String/char-Array
+
+bool psnClient.unsubscribe(char* topic, int length); 
+// param1: Topic String/char-Array
+// param2: Anzahl Zeichen des Topics
+// return true wenn Daten versendet / false wenn nicht
+
+#Daten unter Topic veroeffentlichen 
+int psnClient.publish(char* topic, char* payload); 
+// param1: Topic String/char-Array; 
+// param2: payload-char-Array
+// return: ERROR-Wert: DN_PUBLISH_SUCCESSULL, 
+//                     DN_ERROR_TOPIC_LEN (Topic zu lang - wird abgeschnitten), 
+//                     DN_ERROR_PAYLOAD_LEN (Payload zu lange - wird abgeschnitten)
+
+int psnClient.publish(char* topic, bool payload); 
+// param1: Topic String/char-Array; 
+// param2: payload vom Datentyp bool (wird in char-Array gewandelt)
+// return: ERROR-Wert: DN_PUBLISH_SUCCESSULL, 
+//                     DN_ERROR_TOPIC_LEN (Topic zu lang - wird abgeschnitten), 
+//                     DN_ERROR_PAYLOAD_LEN (Payload zu lange - wird abgeschnitten)
+
+int psnClient.publish(char* topic, int payload); 
+// param1: Topic String/char-Array; 
+// param2: payload vom Datentyp int (wird in char-Array gewandelt)
+// return: ERROR-Wert: DN_PUBLISH_SUCCESSULL, 
+//                     DN_ERROR_TOPIC_LEN (Topic zu lang - wird abgeschnitten), 
+//                     DN_ERROR_PAYLOAD_LEN (Payload zu lange - wird abgeschnitten)
+
+int psnClient.publish(char* topic, int topicLength, char* payload, int payloadLength); 
+// param1: Topic String/char-Array
+// param2: Anzahl Zeichen des Topics
+// param3: payload-char-Array
+// param4: Anzahl Zeichen der Payload
+// return: ERROR-Wert: DN_PUBLISH_SUCCESSULL, 
+//                     DN_ERROR_TOPIC_LEN (Topic zu lang - wird abgeschnitten), 
+//                     DN_ERROR_PAYLOAD_LEN (Payload zu lange - wird abgeschnitten)
+
+//Daten werden beim Zustandswechsel von payload (0->1 / 1->0) veroeffentlicht
+int psnClient.publishOnChange(char* topic, bool payload);
+// param1: Topic String/char-Array; 
+// param2: payload vom Datentyp bool (wird in char-Array gewandelt)
+// return: ERROR-Wert: DN_PUBLISH_SUCCESSULL,
+//                     DN_ERROR_NO_ERROR (Keine Daten veroeffentlicht und keine Fehler), 
+//                     DN_ERROR_TOPIC_LEN (Topic zu lang - wird abgeschnitten), 
+//                     DN_ERROR_PAYLOAD_LEN (Payload zu lange - wird abgeschnitten)
+
+// Daten werden veroeffentlicht, wenn Veränderung von payload groeßer als threshold ist 
+int psnClient.publishOnChange(char* topic, int payload, int threshold);
+// param1: Topic String/char-Array; 
+// param2: payload vom Datentyp bool (wird in char-Array gewandelt)
+// param1: Topic String/char-Array; 
+// return: ERROR-Wert: DN_PUBLISH_SUCCESSULL,
+//                     DN_ERROR_NO_ERROR (Keine Daten veroeffentlicht und keine Fehler), 
+//                     DN_ERROR_TOPIC_LEN (Topic zu lang - wird abgeschnitten), 
+//                     DN_ERROR_PAYLOAD_LEN (Payload zu lange - wird abgeschnitten)
+
+#Callback-Funktion (wird bei neuen Daten aufgerufen)
+//Bezeichnung muss mit der in psnClient.begin(...) übereinstimmen
+void clientCallback(char* topic, int topicLength, char* payload, int payloadLength){...}
+// param1: Topic der Nachricht
+// param2: Lange des Topics
+// param3: Nutdaten der Nachricht
+// param4: Laenge der Nachricht
+```
+
+### Broker
+
+```cpp
+#Anlegen der Broker-Instanz
+// Anlegen des Broker-Objekts
+// psnBroker -> moeglicher Name für Objekt
+didacticPSNetBroker psnBroker; 
+
+#Starten der Broker-Instanz 
+void psnBroker.begin(Stream& sSerial); 
+// param: Schnittstelle (Serial | SoftwareSerial)
+
+#Netzwerkverwaltung Broker (Daten senden und Empfangen, Zugriffsregelung)
+bool psnBroker.handleNetwork();
+// return: true wenn Daten versendet / false wenn nicht
+
+void psnBroker.setInterval(long intervalTime);
+// param: Mindestwartezeit in ms zwischen zwei Sendevorgängen (default 0 ms)
+```
+
+### Hilfreiche Funktionen
+Die Hiflsfunktionen sind als eigenständige Klassen implementiert und koennen so mehrfach (unter verschiedenen Namen) angelegt werden.
+So koennen die Funktionen mehrfach, mit unterschiedlichen Parametern, verwendet werden.
+
+```cpp
+#Flankenerkennung z.B. fuer Taster
+// Anlegen des EdgeDetector-Objekts
+// eDetector -> moeglicher Name für Objekt
+EdgeDetector eDetector;
+
+int eDetector.edgeDetected(bool currentState);
+// param: aktueller binärer Zustand
+// return: 0 -> keine Flanke, RISING, FALLING
+
+#Auf Wertaenderung groeßer Schwellwert pruefen
+// Anlegen des ChangeDetector-Objekts
+// cDetector -> moeglicher Name für Objekt
+ChangeDetector cDetector
+
+bool cDetector.valueChanged(int currentvalue, int threshold);
+// param1: aktueller Wert
+// param2: Schwellwert
+// return: true -> Aenderung groeßer als Schwellwert; sonst false
+
+#Nicht blockierendes Warten
+// Anlegen des UnblockingTimer-Objekts
+// uTimer -> moeglicher Name für Objekt
+UnblockingTimer uTimer;
+
+bool uTimer.timeElapsed(long);
+// param: zu wartende Zeit in Millisekunden
+// return: true, wenn Zeit Wartezeit abgelaufen; sonst false
+
+#Einlesen von Text ueber Serialle Schnittstelle bis Endezeichen empfangen wird
+// Anlegen des SerialReader-Objekts
+// sReader -> moeglicher Name für Objekt
+SerialReader sReader;
+
+int sReader.readSerialData(Stream&, char*, char);
+// param1: Schnittstelle (Serial | SoftSerial)
+// param2: Array in das die Zeichen eingelesen werden
+// param3: Endezeichen (char)
+// return: Anzahl der eingelesenen Zeichen (0 wenn noch kein Endezeichen)
+```
+
+### Konstanten
+
+Konstanten aus der Library die fuer die Programmierung genutzt werden und angepasst werden koennen.
+```cpp
+#ASCII Endezeichen
+DN_ASCII_CR "carriage return CR" (int) 13
+DN_ASCII_NL "new line NL"(int) 10
+
+#Laenge Topics und Payload (Client und Broker)
+MAX_LEN_TOPICS   default: 10
+MAX_LEN_PAYLOAD  default: 20
+
+#Anzahl Topics
+MAX_NR_TOPICS_CLIENT  default: 5
+MAX_NR_TOPICS_BROKER  default: 20
+
+#Mindestwartezeiten zwischen Sendevorgängen (anpassen über psnClient.setInterval())
+INTERVAL_CLIENT	 default: 500 ms
+INTERVAL_BROKER	 default:   0 ms
+
+#ERRORs (nicht verändern)
+DN_PUBLISH_SUCCESSULL 1
+DN_ERROR_NO_ERROR     0
+DN_ERROR_TOPIC_LEN   -1
+DN_ERROR_PAYLOAD_LEN -2
+
+#Frame
+MSG_PRELIMITER '<'
+MSG_DELIMITER  '>'
+MSG_SEPARATOR  '|'
+
+#Dienste
+MSG_PUBLISH     '@'
+MSG_SUBSCRIBE   '?'
+MSG_UPDATE      '#'
+MSG_TOPIC_MULTI '*'
+```
+
+# Bestellung bei Aisler
+
+- Account anlegen
+- Link oeffnen: [Nachkaufprojekt bei Aisler.net](https://aisler.net/p/NBAQNHFV)
+- Projekt importieren (Fehlermeldung / Hinweis ignorieren)
+- Auf eigenen Account zurück gehen
+- unter "Projekte -> Sandbox" befindet sich dann die Platine und die Bauteilliste
+- vor der Bestellung Bauteilliste (Preise) aktualisieren
+- Bestellung der Platinen (Peautiful Boards) und der Bauteile (Precious Parts)
+
+**Hinweis:** Das Projekt letsgoING ist in **keiner Weise** an dem **Verkauf beteiligt**.
\ No newline at end of file
diff --git a/examples/brokerClient/brokerClient.ino b/examples/brokerClient/brokerClient.ino
deleted file mode 100644
index ccabaa076185898ac5dedfff7502f3910b830e80..0000000000000000000000000000000000000000
--- a/examples/brokerClient/brokerClient.ino
+++ /dev/null
@@ -1,215 +0,0 @@
-#include "Arduino.h"
-  #include "SoftwareSerial.h"
-  #include "didacticNet.h"
-
-
-  //#define BROKER
-  #define CLIENT
-  #define C5  // C1 C2 C3 C4 C5
-
-  #define SERIAL_BAUD 2400
-
-  SoftwareSerial sSerial(10, 11);
-
-  #ifdef BROKER
-    didacticPSNetBroker psnB;
-
-    void setup() {
-      Serial.begin(SERIAL_BAUD);
-      sSerial.begin(SERIAL_BAUD);
-      psnB.setStream(sSerial);
-    }
-
-    void loop() {
-      psnB.handleNetwork();
-    }
-  #endif
-
-  #ifdef CLIENT
-    unsigned long lastTime = 0L;
-    byte ledPin3 = 3;
-    byte ledPin5 = 5;
-    byte ledPin6 = 6;
-    byte buttonPin1= 2;
-
-    bool currentState = false;
-    bool lastState    = false;
-    bool togglestate  = true;
-    int lastValue     = 0;
-
-    bool dataReadDone = false;
-    char readData[MAX_LEN_DATA*5]={'\0'};
-    char arrayBuffer[MAX_LEN_DATA+1] = {'\0'};
-    int counter = 0;
-
-    void myCallback(char* mTopic, int mToLength, char* mData, int mDaLength) {
-
-
-    #if defined(C1) || defined(C2) ||  defined(C3) ||  defined(C4)
-      Serial.println("Callback: ");
-      Serial.print("Topic: ");
-      Serial.print(mTopic);
-      Serial.print("\tData: ");
-      Serial.println(mData);
-    #elif defined(C5)
-      Serial.print(mTopic);
-      Serial.print(":\t");
-      Serial.println(mData);
-    #endif
-
-    #if  defined(C1)
-      digitalWrite(ledPin3,(bool)atoi(mData));
-    #elif  defined(C3)
-      analogWrite(ledPin3, map(atoi(mData),0,1023,0,255));
-      analogWrite(ledPin5, map(atoi(mData),0,1023,255,0));
-    #elif  defined(C4)
-      digitalWrite(ledPin3,atoi(mData)<400);
-      digitalWrite(ledPin5,atoi(mData)<400);
-      digitalWrite(ledPin6,atoi(mData)<400);
-    #endif
-    }
-
-  #if  defined(C1)
-    char topicSub[MAX_LEN_TOPICS]={"button1"};
-    char topicPub[MAX_LEN_TOPICS]={"poti1"};
-  #elif  defined(C2)
-    char topicSub[MAX_LEN_TOPICS]={""};
-    char topicPub[MAX_LEN_TOPICS]={"ldr1"};
-  #elif  defined(C3)
-    char topicSub[MAX_LEN_TOPICS]={"poti1"};
-    char topicPub[MAX_LEN_TOPICS]={""};
-  #elif  defined(C4)
-    char topicSub[MAX_LEN_TOPICS]={"ldr1"};
-    char topicPub[MAX_LEN_TOPICS]={"button1"};
-  #elif  defined(C5)
-    char topicSub[MAX_LEN_TOPICS]={""};
-    char topicPub[MAX_LEN_TOPICS]={""};
-  #endif
-
-    didacticPSNetClient psnC;
-    void setup() {
-      Serial.begin(2400);
-      sSerial.begin(2400);
-
-      pinMode(ledPin3, OUTPUT);
-      pinMode(ledPin5, OUTPUT);
-      pinMode(ledPin6, OUTPUT);
-
-      pinMode(buttonPin1, INPUT);
-
-      psnC.setStream(sSerial);
-      psnC.setCallback(myCallback);
-
-      #if defined(C1) ||  defined(C3) ||  defined(C4)
-        psnC.subscribe(topicSub, strlen(topicSub));
-      #endif
-
-      #if defined(C5)
-        Serial.print("Bitte den eigenen Namen mit einem # eingeben\nund mit Enter bestaetigen. -> ");
-        Serial.println("#DeinName");
-        Serial.print("Gebe dann die Namen deiner Chatpartner mit einem ? ein. -> ");
-        Serial.println("@ChatPartner");
-        Serial.println("Anschließend kannst du mit ihnen schreiben");
-        Serial.println();
-        Serial.println("HINWEIS:");
-        Serial.println("Stelle das Zeilenende im SerialMonitor auf \"Zeilenumbruch (CR)\"");
-        Serial.println("*********************************************************************\n");
-      #endif
-    }
-
-    void loop() {
-      psnC.handleNetwork();
-
-    #if defined(C1) ||  defined(C2)
-        int currentValue = analogRead(0);
-        if(abs(currentValue-lastValue) > 20){
-          delay(500);
-          currentValue = analogRead(0);
-          char data[MAX_LEN_DATA]={0};
-          itoa(currentValue, data, 10);
-          psnC.publish(topicPub, strlen(topicPub), data, strlen(data));
-          lastValue = currentValue;
-        }
-    #endif
-
-    #if defined(C3)
-      if(digitalRead(buttonPin1)){
-        togglestate = !togglestate;
-        if(!togglestate){
-          psnC.unsubscribe(topicSub, strlen(topicSub));
-          digitalWrite(ledPin3,LOW);
-          digitalWrite(ledPin5,LOW);
-          digitalWrite(ledPin6,LOW);
-        }
-        else{
-          psnC.subscribe(topicSub, strlen(topicSub));
-        }
-        delay(500);
-      }
-
-    #endif
-
-    #if defined(C4)
-      currentState = digitalRead(buttonPin1);
-      if(lastState != currentState){
-        char data[MAX_LEN_DATA]={0};
-        itoa(currentState, data, 10);
-        psnC.publish(topicPub, strlen(topicPub), data, strlen(data));
-        delay(500);
-      }
-      lastState = currentState;
-    #endif
-
-    #if defined(C5)
-      if(Serial.available()){
-        char buffer = Serial.read();
-        readData[counter] = buffer;
-        if(buffer == 13){
-          readData[counter] = '\0';
-          counter = 0;
-          dataReadDone = true;
-        }else{
-            counter++;
-        }
-      }
-      if(dataReadDone && strlen(readData)<= MAX_LEN_DATA*5 ){
-        if(readData[0] == '@'){
-          strcpy(readData, readData+1);
-          psnC.subscribe(readData, strlen(readData));
-          Serial.print("Kontakt zu ");
-          Serial.print(readData);
-          Serial.println(" hergestellt");
-        }
-        else if(readData[0] == '#'){
-            strcpy(topicPub, readData+1);
-            Serial.print("Dein Name:\t");
-            Serial.println(topicPub);
-          }
-        else {
-          for(int i = 0; i*MAX_LEN_DATA < strlen(readData); i++){
-            memset(arrayBuffer, '\0', MAX_LEN_DATA+1);
-            strncpy(arrayBuffer, &readData[MAX_LEN_DATA*i],MAX_LEN_DATA);
-            //Serial.print("ReadData: ");Serial.print(readData);Serial.print("\t");Serial.print(arrayBuffer);
-            psnC.publish(topicPub, strlen(topicPub), arrayBuffer, strlen(arrayBuffer));
-            while(psnC.isDataToSend()){
-              psnC.handleNetwork();
-            }
-            Serial.print("Ich:\t");
-            Serial.println(arrayBuffer);
-            /*Serial.print(topicPub);
-            Serial.print(" | ");
-            Serial.print(strlen(topicPub));
-            Serial.print(" | ");
-            Serial.print(arrayBuffer);
-            Serial.print(" | ");
-            Serial.print(strlen(arrayBuffer));
-            Serial.print(" | ");
-            Serial.println(i); */
-            //delay(1000);
-          }
-        }
-        dataReadDone = false;
-      }
-    #endif
-  }
-  #endif
diff --git a/examples/sPSN_Broker/sPSN_Broker.ino b/examples/sPSN_Broker/sPSN_Broker.ino
index 662ecf03641f9d69a3289d9f9be861024f9514bd..e2d142d2644ba0defd9a1c018852432d4ff17448 100644
--- a/examples/sPSN_Broker/sPSN_Broker.ino
+++ b/examples/sPSN_Broker/sPSN_Broker.ino
@@ -26,7 +26,7 @@
  *date:  14.12.2020
  *version: 1.0
  */
-
+#include <Arduino.h>
 #include "SoftwareSerial.h"
 #include "didacticNet.h"
 
@@ -38,7 +38,7 @@
 SoftwareSerial sSerial(10, 11);
 
 //Erzeuge Broker-Instanz
-didacticPSNetBroker psnBroker;
+DidacticPSNetBroker psnBroker;
 
 void setup() {
   //Starte Serielle Schnittstelle (zum PC)
@@ -56,3 +56,5 @@ void loop() {
   //hier verarbeitet der Broker alle Daten
   psnBroker.handleNetwork();
 }
+
+
diff --git a/examples/sPSN_Chat/sPSN_Chat.ino b/examples/sPSN_Chat/sPSN_Chat.ino
index df7dbe6bdd0abbdab2821ce70bb16757a8f9e34f..e7b228bf1438dc7015d2dcc90f5f7b8953117193 100644
--- a/examples/sPSN_Chat/sPSN_Chat.ino
+++ b/examples/sPSN_Chat/sPSN_Chat.ino
@@ -1,84 +1,69 @@
 /**
- *file:  sPSN_Chat.ino
- *author:  letsgoING -> info@letsgoing.de
+ * file:  sPSN_Chat.ino
+ * author:  letsgoING -> info@letsgoing.de
+ * 
+ * description:
+ *   Dieses Programm ist ein Teil eines Beispiels für ein einfaches Pub-Sub-Chat-Netzwerk.
  *
- *description:
- * Dieses Programm ist ein Teil eines Beispiels für ein einfaches Pub-Sub-Chat-Netzwerk.
-
- * Für dieses Chat-Netzwerk werden mindestens 3 Arduinos benötigt:
+ *   Für dieses Chat-Netzwerk werden mindestens 3 Arduinos benötigt:
  *
- * Arduino1:   sPSN_Broker.ino
- *            - IR-Sender an Pin 11 IR-Empfänger an Pin10
+ *   Arduino1:   sPSN_Broker.ino
+ *              - IR-Sender an Pin 11 IR-Empfänger an Pin10
  *
- * Arduino2-n: sPSN_Chat.ino (dieses Programm)
- *            - IR-Sender an Pin 11 IR-Empfänger an Pin10
+ *   Arduino2-n: sPSN_Chat.ino (dieses Programm)
+ *              - IR-Sender an Pin 11 IR-Empfänger an Pin10
  * Funktion:
- * Am Arduino2-n kann ein eigner Name (Sende-Topic) angeben werden.
- * Danach kann angeben werden wem zugehört werden soll (Empfangs-Topics).
- * Arduino1 (Server) übernimmt das Verteilen der Nachrichten.
+ *   Am Arduino2-n kann ein eigner Name (Sende-Topic) angeben werden.
+ *   Danach kann angeben werden wem zugehört werden soll (Empfangs-Topics).
+ *   Arduino1 (Server) übernimmt das Verteilen der Nachrichten.
  *
- *date:  14.12.2020
- *version: 1.0
- */
-
+ * parameter:
+ *   MAX_LEN_PAYLOAD = 20 Zeichen (didacticNet.h)
+ *   MAX_LEN_TOPICS = 10 Zeichen (didacticNet.h)
+ *   max Laenge der Eingegebenen Daten: 100 Zeichen (5*MAX_LEN_PAYLOAD)
+ *
+ * date:  13.07.2021
+*/
+#include <Arduino.h>
 #include "SoftwareSerial.h"
 #include "didacticNet.h"
 
-//lege Geschwindigkeit für serielle Schnittstellen fest
-#define SERIAL_BAUD 2400
-
-
-unsigned long lastTime = 0L;
+#define SERIAL_BAUD 2400                         //lege Geschwindigkeit für serielle Schnittstellen fest
 
-bool dataReadDone = false;
+char readData[MAX_LEN_PAYLOAD * 5]      = {'\0'};  //Array für eingelesene Daten (mit Puffer für zu lange Eingaben)
 
-//Maximale Nachrichten- und Topic-Länge:
-//MAX_LEN_DATA = 20 Zeichen
-//MAX_LEN_TOPICS = 10 Zeichen
-//kann erhöht werden (z. B. #define MAX_LEN_TOPICS 20) , dann aber Arduino-Mega als Server sinnvoll
+char topicSub[MAX_LEN_TOPICS] = {""};           //Array für neues Empfangs-Topic
+char topicPub[MAX_LEN_TOPICS] = {""};           //Array für eigenes Sende-Topic
 
-char readData[MAX_LEN_DATA * 5] = {'\0'};
-char arrayBuffer[MAX_LEN_DATA + 1] = {'\0'};
-int counter = 0;
-
-//Arrays für Empfangs- und Sende Topic
-char topicSub[MAX_LEN_TOPICS] = {""};
-char topicPub[MAX_LEN_TOPICS] = {""};
-
-void myCallback(char* mTopic, int mToLength, char* mData, int mDaLength) {
+//Callback-Funktion wird bei neuen Daten automatisch aufgerufen
+void clientCallback(char* mTopic, int mToLength, char* mData, int mDaLength) {
   Serial.print(mTopic);
   Serial.print(":\t");
   Serial.println(mData);
 }
 
-//lege Pins für SoftwareSerielle Schnittstelle fest
-// Rx = 10 -> Empfänger | Tx = 11 -> Sender
-SoftwareSerial sSerial(10, 11);
+SoftwareSerial sSerial(10, 11); // SoftwareSerial an Rx = Pin10 -> Empfänger | Tx = Pin11 -> Sender
 
-//Erzeuge Client-Instanz
-didacticPSNetClient psnClient;
+DidacticPSNetClient psnClient; //Erzeuge PubSub-Client-Instanz
+SerialReader sReader;
 
 
 void setup() {
-  //Starte Serielle Schnittstelle (zum PC)
-  Serial.begin(SERIAL_BAUD);
 
-  //Starte SoftwareSerielle Schnittstelle (zu IR-Link-Modulen)
-  sSerial.begin(SERIAL_BAUD);
+  Serial.begin(SERIAL_BAUD);  //Starte Serielle Schnittstelle (zum PC)
 
-  //Lege fest welche Serielle Schnittstelle für sPSN verwendet werden soll
-  //psnClient.setStream(sSerial);
+  sSerial.begin(SERIAL_BAUD); //Starte SoftwareSerielle Schnittstelle (zu IR-Link-Modulen)
 
-  //Lege Callback-Funktion fest (wird ausgeführt wenn neue Daten ankommen)
-  //psnClient.setCallback(myCallback);
-
-  psnClient.begin(sSerial, myCallback);
+  psnClient.begin(sSerial, clientCallback); //Starte PubSubClient mit SoftwareSerial und Callbackfunktion "clientCallback"
+  sReader.begin(Serial);
 
+  //AUSGABE INFOTEXT
   Serial.print("Bitte den eigenen Namen mit einem # eingeben\nund mit Enter bestaetigen. -> ");
   Serial.println("#DeinName");
   Serial.print("Gebe dann die Namen deiner Chatpartner mit einem @ ein. -> ");
   Serial.println("@ChatPartner");
-  Serial.println("Anschließend kannst du mit ihnen schreiben");
+  Serial.println("Anschließend kannst du mit ihnen schreiben.");
+  Serial.println("Pro Nachricht duerfen maximal 20 Zeichen eingegeben werden!");
   Serial.println();
   Serial.println("HINWEIS:");
   Serial.println("Stelle das Zeilenende im SerialMonitor auf \"Zeilenumbruch (CR)\"");
@@ -86,60 +71,44 @@ void setup() {
 }
 
 void loop() {
-  //Verarbeiten der Daten, prüfen ob Netzwerk frei und versenden der Daten
-  psnClient.handleNetwork();
-
-  //Lese Daten ein bis zum Zeichen Zeilenumbruch "CR"
-  if (Serial.available()) {
-    char buffer = Serial.read();
-    readData[counter] = buffer;
-    //Wenn Zeilenumbruch "CR", dann merke, dass Einlesen fertig
-    //und setze String Abschluss "\0" ans Ende
-    if (buffer == 13) {
-      readData[counter] = '\0';
-      counter = 0;
-      dataReadDone = true;
-    } else {
-      counter++;
+
+  psnClient.handleNetwork();  //Verarbeiten der Daten, prüfen ob Netzwerk frei und versenden der Daten
+
+  int nrOfAscii = sReader.readSerialData(readData, DN_ASCII_CR); //Einlesen der Nutzereingabe am SerialMonitor (Rueckgabewert = Anzahl der gelesenen Zeichen)
+
+  if (nrOfAscii > 0) { //Wenn Daten fertig eingelesen wurden
+
+    if (readData[0] == '@') {         //Wenn '@' vorne steht, dann neuer Chatpartner anlegen (neues Topic abonnieren)
+      strcpy(readData, &readData[1]); //verschiebe um ein Zeichen (entferne '@')
+      psnClient.subscribe(readData);  //Lege fest zu welchem Topic Daten empfangen werden sollen (den Namen des Chatpartners)
+
+      Serial.print("Nachrichten von "); //Ausgabe welches Topic abonniert wurde
+      Serial.print(readData);
+      Serial.println(" abonniert.");
     }
-  }
+    else if (readData[0] == '!') {         //Wenn '@' vorne steht, dann neuer Chatpartner anlegen (neues Topic abonnieren)
+      strcpy(readData, &readData[1]); //verschiebe um ein Zeichen (entferne '!')
+      psnClient.unsubscribe(readData);  //Lege fest zu welchem Topic Daten empfangen werden sollen (den Namen des Chatpartners)
 
-  //Wenn Daten fertig eingelesen wurden
-  if (dataReadDone && strlen(readData) <= MAX_LEN_DATA * 5 ) {
-    //Wenn "@" vorne steht, dann neuer Chatpartner anlegen (neues Topic dem zugehört wird)
-    if (readData[0] == '@') {
-      //kopiere das neue Topic (den Namen des Chatpartners) in das passende Array
-      strcpy(readData, readData + 1);
-      //Lege fest zu welchem Topic Daten empfangen werden sollen (den Namen des Chatpartners)
-      psnClient.subscribe(readData);
-      Serial.print("Kontakt zu ");
+      Serial.print("Nachrichten von "); //Ausgabe welches Topic abonniert wurde
       Serial.print(readData);
-      Serial.println(" hergestellt");
+      Serial.println(" nicht mehr abonniert.");
     }
-    //Wenn "#" vorne steht, dann neuer eigener Name (neues Topic unter dem gesendet wird)
-    else if (readData[0] == '#') {
-      //kopiere das neue Topic (deinen neuen Namen) in das passende Array
-      strcpy(topicPub, readData + 1);
-      Serial.print("Dein Name:\t");
+
+    else if (readData[0] == '#') {    //Wenn '#' vorne steht, dann neuer eigener Name (neues Topic unter dem gesendet wird)
+      //strcpy(topicPub, readData + 1); //kopiere das neue Topic (deinen neuen Namen) in das passende Array (+ 1 = entferne '#')
+      strcpy(topicPub, &readData[1]); //kopiere das neue Topic (deinen neuen Namen) in das passende Array (+ 1 = entferne '#')
+      
+      Serial.print("Dein Name:\t");   //Ausgabe unter welchem Topic veröffentlicht wird
       Serial.println(topicPub);
     }
-    //Wenn normale Nachrichten eingegeben wurden, dann Daten unter eigenem Topic versenden
-    else {
-      for (int i = 0; i * MAX_LEN_DATA < strlen(readData); i++) {
-        memset(arrayBuffer, '\0', MAX_LEN_DATA + 1);
-        strncpy(arrayBuffer, &readData[MAX_LEN_DATA * i], MAX_LEN_DATA);
-        //Serial.print("ReadData: ");Serial.print(readData);Serial.print("\t");Serial.print(arrayBuffer);
-        psnClient.publish(topicPub, arrayBuffer);
-        //Solange Daten zu versenden sind (wenn Text länger als max Länge einer Nachricht)
-        while (psnClient.isDataToSend()) {
-          //Verarbeiten der Daten, prüfen ob Netzwerk frei und versenden der Daten
-          psnClient.handleNetwork();
-        }
-        Serial.print("Ich:\t");
-        Serial.println(arrayBuffer);
-      }
+
+    else { //Wenn "normale" Nachrichten eingegeben wurden, dann Daten unter eigenem Topic versenden
+      psnClient.publish(topicPub, readData);  //Bereite eingegebene Daten zum Senden vor
+      
+      Serial.print("Ich:\t");   //Ausgabe was unter deinem Topic veröffentlicht wird
+      Serial.println(readData);
     }
-    dataReadDone = false;
   }
 
-}
+}
\ No newline at end of file
diff --git a/examples/sPSN_Client1/sPSN_Client1.ino b/examples/sPSN_Client1/sPSN_Client1.ino
index 61997358952e0f61d7bcbb755b57b0f1135b7650..e17005086f286493089dcf3ca436d9ab92b2147f 100644
--- a/examples/sPSN_Client1/sPSN_Client1.ino
+++ b/examples/sPSN_Client1/sPSN_Client1.ino
@@ -7,115 +7,76 @@
  * Für das Netwerk werden 3 Arduinos mit IR-Link-Modulen benötigt:
  *
  * Arduino1: sPSN_Broker.ino
- *           - IR-Sender an Pin 11 IR-Empfänger an Pin10
+ * 
+ * Arduino2: sPSN_Client1.ino (dieses Programm)  -> Sendet Wert des Potis | Empfängt Zustand des Tasters
+ * (Poti an PinA0 | LED an Pin5)
+ * 
+ * Arduino3: sPSN_Client2.ino -> Sendet Zustand des Tasters | Empfängt Wert des Potis
+ * (Taster an Pin2 | LED an Pin5)
  *
- * Arduino2: sPSN_Client1.ino (dieses Programm)
- *           - IR-Sender an Pin 11 IR-Empfänger an Pin10
- *           - Taster an Pin2
- *           - LED an Pin9
- *
- * Arduino3: sPSN_Client2.ino
- *           - IR-Sender an Pin 11 IR-Empfänger an Pin10
- *           - Poti an PinA0
- *           - LED an Pin9
- *
- * Funktion:
- * Mit dem Poti an Arduino3 kann die LED am Arduino2 gedimmt werden.
- * Mit dem Taster an Arduino2 kann die LED an Arduino2 ein-/ausgeschaltet werden.
- * Arduino1 übernimmt das Verteilen der Nachrichten.
- *
- *date:  14.12.2020
- *version: 1.0
+ * parameter:
+ *  MAX_LEN_PAYLOAD = 20 Zeichen (didacticNet.h)
+ *  MAX_LEN_TOPICS = 10 Zeichen (didacticNet.h)
+ * 
+ *date:  06.07.2021
  */
-
+#include <Arduino.h>
 #include "SoftwareSerial.h"
 #include "didacticNet.h"
 
-//lege Geschwindigkeit für serielle Schnittstellen fest
-#define SERIAL_BAUD 2400
+#define SERIAL_BAUD 2400 //lege Geschwindigkeit für serielle Schnittstellen fest
 
+#define LED_PIN   5
+#define POTI_PIN A0
 
-byte ledPin    = 9;
-byte potiPin   = A0;
+#define THRESHOLD   10  //Schwellwert für min. Wertänderung
 
-int lastValue     = 0;
+char topicPublish[MAX_LEN_TOPICS]   = "potiVal";  //Topic unter dem (eigene) Daten veröffentlicht werden
+char topicSubscribe[MAX_LEN_TOPICS] = "btnState"; //Topic (von anderem TN) das abboniert werden soll
 
+char payload[MAX_LEN_PAYLOAD] = {0};
 
-//Maximale Nachrichten- und Topic-Länge:
-//MAX_LEN_DATA = 20 Zeichen
-//MAX_LEN_TOPICS = 10 Zeichen
-//kann erhöht werden (z. B. #define MAX_LEN_TOPICS 20) , dann aber Arduino-Mega als Server sinnvoll
+SoftwareSerial sSerial(10, 11); //Erzeuge SoftwareSerial-Instanz mit Rx = Pin10 -> Empfänger | Tx = Pin11 -> Sender
 
-//Arrays für Empfangs- und Sende Topic
-char topicSub[MAX_LEN_TOPICS] = "buttonVal";
-char topicPub[MAX_LEN_TOPICS] = "potiVal";
+DidacticPSNetClient psnClient;  //Erzeuge PubSub-Client-Instanz
 
-void myCallback(char* mTopic, int mToLength, char* mData, int mDaLength) {
-  Serial.println("Callback: ");
-  Serial.print("Topic: ");
+
+//Callback-Funktion - wird beim Empfang neuer Daten aufgerufen
+void clientCallback(char* mTopic, int mToLength, char* mData, int mDaLength) {
+  Serial.print("CB: ");
   Serial.print(mTopic);
-  Serial.print("\tData: ");
+  Serial.print(" | ");
   Serial.println(mData);
 
-  //Setze Ausgang entsprechend dem gesendeten Wert
-  digitalWrite(ledPin, (bool)atoi(mData));
+  boolean static stateLED = false;
+  
+  //Wechsle Zustand der Variable "stateLED" wenn Taster beim Sender gedrueckt wurde
+  if(bool(atoi(mData)) == true){
+    stateLED = !stateLED;
+    digitalWrite(LED_PIN, stateLED);              //Setze Ausgang entsprechend dem empfangenen Wert
+  }        
 }
 
 
-//lege Pins für SoftwareSerielle Schnittstelle fest
-// Rx = 10 -> Empfänger | Tx = 11 -> Sender
-SoftwareSerial sSerial(10, 11);
-
-//Erzeuge Client-Instanz
-didacticPSNetClient psnClient;
-
-
 void setup() {
-  //Starte Serielle Schnittstelle (zum PC)
-  Serial.begin(SERIAL_BAUD);
-
-  Serial.print("\nStarting sPSNet: \nlistening to:\t");
-  Serial.println(topicSub);
-  Serial.print("sending to:\t");
-  Serial.println(topicPub);
+  
+  Serial.begin(SERIAL_BAUD);    //Starte Serielle Schnittstelle (zum PC)
+  sSerial.begin(SERIAL_BAUD);   //Starte SoftwareSerielle Schnittstelle (zu IR-Link-Modulen)
 
-  //Starte SoftwareSerielle Schnittstelle (zu IR-Link-Modulen)
-  sSerial.begin(SERIAL_BAUD);
+  pinMode(LED_PIN,OUTPUT);
 
-  pinMode(ledPin, OUTPUT);
+  psnClient.begin(sSerial, clientCallback); //Starte PubSub Client an SoftwareSerial Schnittstelle
+  //psnClient.begin(Serial, clientCallback); //Starte PubSub Client an Serial Schnittstelle
 
-  //Lege fest welche Serielle Schnittstelle für sPSN verwendet werden soll
-  //psnClient.setStream(sSerial);
+  psnClient.subscribe(topicSubscribe); //Lege fest zu welchem Topic Daten empfangen werden sollen
+}
 
-  //Lege Callback-Funktion fest (wird ausgeführt wenn neue Daten ankommen)
-  //psnClient.setCallback(myCallback);
+void loop() {
 
-  psnClient.begin(sSerial, myCallback);
+  psnClient.handleNetwork();               //Verarbeiten der Daten, prüfen ob Netzwerk frei und versenden der Daten
 
-  //Lege fest zu welchem Topic Daten empfangen werden sollen
-  psnClient.subscribe(topicSub);
+  int currentValue = analogRead(POTI_PIN); //lese Poti ein und speichere Wert
+  psnClient.publishOnChange(topicPublish, currentValue, THRESHOLD); 
+  
 }
 
-void loop() {
-  //Verarbeiten der Daten, prüfen ob Netzwerk frei und versenden der Daten
-  psnClient.handleNetwork();
-
-  //lese Poti ein und speichere Wert
-  int currentValue = analogRead(potiPin);
-
-  //Übertrage Werte nur, wenn sie sich geändert haben
-  if (abs(currentValue - lastValue) > 20) {
-    //warte kurz, um nicht zu oft zu senden
-    delay(500);
-    //lese den Poti erneut ein
-    currentValue = analogRead(potiPin);
-    //setze den Inhalt des Puffer-Arrays auf 0
-    char data[MAX_LEN_DATA] = {0};
-    //wandle int-Wert in ASCII-Zeichen
-    itoa(currentValue, data, 10);
-    //sende analog-Wert
-    psnClient.publish(topicPub, data);
-    //speichere aktuellen Wert, um zu erkennen, ob er sich ändert
-    lastValue = currentValue;
-  }
-}
diff --git a/examples/sPSN_Client2/sPSN_Client2.ino b/examples/sPSN_Client2/sPSN_Client2.ino
index dc3be3bf1df9dec594464c653d6dfe7714bc963f..5e49f515a0ae66a38edcbd61446f3009e42a0ba3 100644
--- a/examples/sPSN_Client2/sPSN_Client2.ino
+++ b/examples/sPSN_Client2/sPSN_Client2.ino
@@ -1,119 +1,78 @@
 /**
- *file:  sPSN_Client2
+ *file:  sPSN_Client1
  *author:  letsgoING -> info@letsgoing.de
  *
  *description:
  * Dieses Programm ist ein einfaches Beispiel für ein einfaches Pub-Sub-Netzwerk.
  * Für das Netwerk werden 3 Arduinos mit IR-Link-Modulen benötigt:
  *
- * Arduino1: sPSN_Broker..ino
- *           - IR-Sender an Pin 11 IR-Empfänger an Pin10
+ * Arduino1: sPSN_Broker.ino
+ * 
+ * Arduino2: sPSN_Client1.ino -> Sendet Wert des Potis | Empfängt Zustand des Tasters
+ * (Poti an PinA0 | LED an Pin5)
+ * 
+ * Arduino3: sPSN_Client2.ino (dieses Programm) -> Sendet Zustand des Tasters | Empfängt Wert des Potis
+ * (Taster an Pin2 | LED an Pin5)
  *
- * Arduino2: sPSN_Client1.ino
- *           - IR-Sender an Pin 11 IR-Empfänger an Pin10
- *           - Taster an Pin2
- *           - LED an Pin9
- *
- * Arduino3: sPSN_Client2.ino (dieses Programm)
- *           - IR-Sender an Pin 11 IR-Empfänger an Pin10
- *           - Poti an PinA0
- *           - LED an Pin9
- *
- * Funktion:
- * Mit dem Poti an Arduino3 kann die LED am Arduino2 gedimmt werden.
- * Mit dem Taster an Arduino2 kann die LED an Arduino2 ein-/ausgeschaltet werden.
- * Arduino1 übernimmt das Verteilen der Nachrichten.
- *
- *date:  14.12.2020
- *version: 1.0
+ *date:  06.07.2021
  */
 
+#include <Arduino.h>
 #include "SoftwareSerial.h"
 #include "didacticNet.h"
 
-//lege Geschwindigkeit für serielle Schnittstellen fest
-#define SERIAL_BAUD 2400
+#define SERIAL_BAUD 2400 //lege Geschwindigkeit für serielle Schnittstellen fest
 
-byte ledPin    = 9;
-byte buttonPin = 2;
+#define LED_PIN    5
+#define LED2_PIN    6
+#define BUTTON_PIN 2
 
-bool lastState     = 0;
+char topicPublish[MAX_LEN_TOPICS]   = "btnState";   //Topic unter dem (eigene) Daten veröffentlicht werden
+char topicSubscribe[MAX_LEN_TOPICS] = "potiVal";    //Topic (von anderem TN) das abboniert werden soll
 
-//Maximale Nachrichten- und Topic-Länge:
-//MAX_LEN_DATA = 20 Zeichen
-//MAX_LEN_TOPICS = 10 Zeichen
-//kann erhöht werden (z. B. #define MAX_LEN_TOPICS 20) , dann aber Arduino-Mega als Server sinnvoll
+char payload[MAX_LEN_PAYLOAD] = {0};
+boolean newData  = false;
+boolean ledState = false;
 
-//Arrays für Empfangs- und Sende Topic
-char topicSub[MAX_LEN_TOPICS] = {"potiVal"};
-char topicPub[MAX_LEN_TOPICS] = {"buttonVal"};
+SoftwareSerial sSerial(10, 11); //Erzeuge SoftwareSerial-Instanz mit Rx = Pin10 -> Empfänger | Tx = Pin11 -> Sender
 
-void myCallback(char* mTopic, int mToLength, char* mData, int mDaLength) {
-  Serial.println("Callback: ");
-  Serial.print("Topic: ");
-  Serial.print(mTopic);
-  Serial.print("\tData: ");
-  Serial.println(mData);
+DidacticPSNetClient psnClient;  //Erzeuge PubSub-Client-Instanz
+UnblockingTimer uTimer;
 
-  //Setze Ausgang entsprechend dem gesendeten Wert
-  analogWrite(ledPin, map(atoi(mData), 0, 1023, 0, 255));
-}
 
+//Callback-Funktion - wird beim Empfang neuer Daten aufgerufen
+void clientCallback(char* mTopic, int mToLength, char* mData, int mDaLength) {
+  Serial.print("CB: ");
+  Serial.print(mTopic);
+  Serial.print(" | ");
+  Serial.println(mData);
 
-//lege Pins für SoftwareSerielle Schnittstelle fest
-// Rx = 10 -> Empfänger | Tx = 11 -> Sender
-SoftwareSerial sSerial(10, 11);
+  int valuePoti = atoi(mData);  //wandle ASCII-Zeichen in Wert
+  //Alternativ: sscanf(mData, "%d", &stateLED); //wandle ASCII-Zeichen in Wert
 
-//Erzeuge Client-Instanz
-didacticPSNetClient psnClient;
+  int valueLED = constrain(map(valuePoti, 0, 1023, 0, 255), 0, 255); //passe analogRead-Wert für analogWrite an
+  
+  analogWrite(LED_PIN, valueLED);        //Setze Ausgang entsprechend dem empfangenen Wert
+  analogWrite(LED2_PIN, 255-valueLED);   //Setze Ausgang invertiert zum empfangenen Wert
+}
 
 
 void setup() {
-  //Starte Serielle Schnittstelle (zum PC)
-  Serial.begin(SERIAL_BAUD);
-
-  Serial.print("\nStarting sPSNet: \nlistening to:\t");
-  Serial.println(topicSub);
-  Serial.print("sending to:\t");
-  Serial.println(topicPub);
+  
+  Serial.begin(SERIAL_BAUD);    //Starte Serielle Schnittstelle (zum PC)
+  sSerial.begin(SERIAL_BAUD);   //Starte SoftwareSerielle Schnittstelle (zu IR-Link-Modulen)
 
-  //Starte SoftwareSerielle Schnittstelle (zu IR-Link-Modulen)
-  sSerial.begin(SERIAL_BAUD);
+  psnClient.begin(sSerial, clientCallback); //Starte PubSub Client an SoftwareSerial Schnittstelle
+  //psnClient.begin(Serial, clientCallback); //Starte PubSub Client an Serial Schnittstelle
 
-  pinMode(ledPin, OUTPUT);
-  pinMode(buttonPin, INPUT);
-
-  //Lege fest welche Serielle Schnittstelle für sPSN verwendet werden soll
-  //psnClient.setStream(sSerial);
+  psnClient.subscribe(topicSubscribe); //Lege fest zu welchem Topic Daten empfangen werden sollen
+}
 
-  //Lege Callback-Funktion fest (wird ausgeführt wenn neue Daten ankommen)
-  //psnClient.setCallback(myCallback);
+void loop() {
 
-  psnClient.begin(sSerial, myCallback);
+  psnClient.handleNetwork();               //Verarbeiten der Daten, prüfen ob Netzwerk frei und versenden der Daten
 
-  //Lege fest zu welchem Topic Daten empfangen werden sollen
-  psnClient.subscribe(topicSub);
+  boolean buttonState = digitalRead(BUTTON_PIN); //lese Taster ein und speichere Wert
+  psnClient.publishOnChange(topicPublish, buttonState); //bereite Topic und Nutzdaten zum senden vor, wenn sich buttonState ändert
 }
 
-void loop() {
-  //Verarbeiten der Daten, prüfen ob Netzwerk frei und versenden der Daten
-  psnClient.handleNetwork();
-
-  //lese aktuellen Zustand des Tasters ein
-  bool currentState = digitalRead(buttonPin);
-
-  //Wenn Flanke erkannt (fallend/steigend) dann übertrage den aktuellen Wert
-  if (lastState != currentState) {
-    //setze den Inhalt des Puffer-Arrays auf 0
-    char data[MAX_LEN_DATA] = {0};
-    //wandle bool-Wert in ASCII-Zeichen
-    itoa(currentState, data, 10);
-    //sende digital-Wert
-    psnClient.publish(topicPub, data);
-    //warte kurz, um nicht zu oft zu senden
-    delay(500);
-  }
-
-  //speichere aktuellen Wert, um zu erkennen, ob er sich ändert
-  lastState = currentState;
-}
diff --git a/examples/sPSN_ClientMinimal/sPSN_ClientMinimal.ino b/examples/sPSN_ClientMinimal/sPSN_ClientMinimal.ino
new file mode 100644
index 0000000000000000000000000000000000000000..1805cb58108e1a730c26dcee0223ef58ced973e2
--- /dev/null
+++ b/examples/sPSN_ClientMinimal/sPSN_ClientMinimal.ino
@@ -0,0 +1,60 @@
+/**
+ *file:  sPSN_Client1
+ *author:  letsgoING -> info@letsgoing.de
+ *
+ *description:
+ * Dieses Programm ist das Minimal-Beispiel für ein einfaches Pub-Sub-Netzwerk.
+ * Es wird jede Sekunde ein analoger Messwert (AO) übertragen 
+ * und die empfangenen Daten auf dem SerialMonitor ausgegeben
+ * 
+ * Für das Netwerk werden 3 oder mehr Arduinos mit IR-Link-Modulen benötigt:
+ *
+ * Arduino1: sPSN_Broker.ino
+ * 
+ * Arduino2-n: sPSN_ClientMinimal.ino (dieses Programm)  
+ * 
+ * parameter:
+ *  MAX_LEN_PAYLOAD = 20 Zeichen (didacticNet.h)
+ *  MAX_LEN_TOPICS = 10 Zeichen (didacticNet.h)
+ * 
+ *date:  06.07.2021
+ */
+#include <Arduino.h>
+#include "SoftwareSerial.h"
+#include "didacticNet.h"
+
+SoftwareSerial sSerial(10, 11); //Erzeuge SoftwareSerial-Instanz mit Rx = Pin10 -> Empfänger | Tx = Pin11 -> Sender
+
+DidacticPSNetClient psnClient;  //Erzeuge PubSub-Client-Instanz
+UnblockingTimer uTimer;
+
+//Callback-Funktion - wird beim Empfang neuer Daten aufgerufen
+void clientCallback(char* mTopic, int mToLength, char* mPayload, int mPayloadLength) {
+  Serial.print("Nachricht von: ");
+  Serial.print(mTopic);
+  Serial.print(" - ");
+  Serial.println(mPayload);
+}
+
+
+void setup() {
+  
+  Serial.begin(2400);    //Starte Serielle Schnittstelle (zum PC)
+  sSerial.begin(2400);   //Starte SoftwareSerielle Schnittstelle (zu IR-Link-Modulen)
+
+  psnClient.begin(sSerial, clientCallback); //Starte PubSub Client an SoftwareSerial Schnittstelle
+  
+  //Hier EMPFANGS-TOPIC ANPASSEN -> default "client2"
+  psnClient.subscribe("client2");           //Lege fest zu welchem Topic Daten empfangen werden sollen
+}
+
+void loop() {
+
+  psnClient.handleNetwork();         //Verarbeiten der Daten, prüfen ob Netzwerk frei und versenden der Daten
+
+  int currentValue = analogRead(A0); //lese Poti ein und speichere Wert
+  
+  //Hier SENDE-TOPIC ANPASSEN -> default "client1"
+  psnClient.publish("client1", currentValue);
+}
+
diff --git a/examples/sPSN_PingTest/sPSN_PingTest.ino b/examples/sPSN_PingTest/sPSN_PingTest.ino
new file mode 100644
index 0000000000000000000000000000000000000000..03f7594556151735e92def76407c3ca8c2ca223f
--- /dev/null
+++ b/examples/sPSN_PingTest/sPSN_PingTest.ino
@@ -0,0 +1,114 @@
+/**
+  file:  sPSN_HWTest
+  author:  letsgoING -> info@letsgoing.de
+
+  description:
+   Test-Software um Clients im Netzwerk "anzumelden"
+
+  date:  01.12.2021
+*/
+
+/**
+ *file:  sPSN_PingTest
+ *author:  letsgoING -> info@letsgoing.de
+ *
+ *description:
+ * Test-Software um Clients im Netzwerk "anzumelden"
+ * Für das Netwerk werden min. 3 Arduinos mit IR-Link-Modulen benötigt:
+ *
+ * Arduino1: sPSN_Broker.ino
+ * 
+ * Arduino2: sPSN_PongTester.ino -> fragt Clients ab
+ * 
+ * Arduino3: sPSN_PingTest.ino -> reagiert auf PongTester
+ * 
+ *date:  01.12.2021
+ */
+
+#include "Arduino.h"
+
+#include "SoftwareSerial.h"
+#include "didacticNet.h"
+
+//lege Geschwindigkeit für serielle Schnittstellen fest
+#define SERIAL_BAUD 2400
+
+//HIER CLIENT-NUMMER ANPASSEN
+//*******************************
+#define MY_NUMBER  1
+//*******************************
+
+#define LED_PIN    5
+#define LED2_PIN   6
+#define BUTTON_PIN 2
+
+
+//lege Pins für SoftwareSerielle Schnittstelle fest
+// Rx = 10 -> Empfänger | Tx = 11 -> Sender
+SoftwareSerial sSerial(10, 11);
+
+//Erzeuge Client-Instanz
+DidacticPSNetClient psnClient;
+
+EdgeDetector eDetector;
+
+//Arrays für Empfangs- und Sende Topic
+char topicSub[MAX_LEN_TOPICS] = "";
+char topicPub[MAX_LEN_TOPICS] = "";
+
+char payloadSend[] = "Ping";
+
+bool ledState = true;
+
+void myCallback(char* mTopic, int mToLength, char* mData, int mDaLength) {
+  Serial.println(mData);
+  digitalWrite(LED_BUILTIN, HIGH);
+}
+
+
+void setup() {
+  //Starte Serielle Schnittstelle (zum PC)
+  Serial.begin(SERIAL_BAUD);
+  delay(2000);
+
+  sprintf(topicPub, "%02d", MY_NUMBER);
+  sprintf(topicSub, "%02d", MY_NUMBER);
+
+  Serial.print("\nStarting sPSNet as Client ");
+  Serial.println(topicPub);
+
+
+  //Starte SoftwareSerielle Schnittstelle (zu IR-Link-Modulen)
+  sSerial.begin(SERIAL_BAUD);
+
+  pinMode(LED_BUILTIN, OUTPUT);
+  pinMode(LED_PIN, OUTPUT);
+  pinMode(LED2_PIN, OUTPUT);
+
+  digitalWrite(LED_BUILTIN, LOW);
+  digitalWrite(LED_PIN, ledState);
+  digitalWrite(LED2_PIN, ledState);
+
+  psnClient.begin(sSerial, myCallback);
+
+  psnClient.publish(topicPub, payloadSend);
+  while (!psnClient.handleNetwork());
+
+  psnClient.subscribe(topicSub);
+  while (!psnClient.handleNetwork());
+
+  psnClient.setInterval(10000L);
+}
+
+void loop() {
+  //Verarbeiten der Daten, prüfen ob Netzwerk frei und versenden der Daten
+  psnClient.handleNetwork();
+
+  psnClient.publish(topicPub, payloadSend);
+
+  if (eDetector.edgeDetected(digitalRead(BUTTON_PIN)) == RISING) {
+    ledState = !ledState;
+    digitalWrite(LED_PIN, !ledState);
+    digitalWrite(LED2_PIN, ledState);
+  }
+}
diff --git a/examples/sPSN_PongTester/sPSN_PongTester.ino b/examples/sPSN_PongTester/sPSN_PongTester.ino
new file mode 100644
index 0000000000000000000000000000000000000000..bddbb0f9f95248e967c2bb387d899600e7140c44
--- /dev/null
+++ b/examples/sPSN_PongTester/sPSN_PongTester.ino
@@ -0,0 +1,93 @@
+
+/**
+ *file:  sPSN_PongTester
+ *author:  letsgoING -> info@letsgoing.de
+ *
+ *description:
+ * Test-Software um Clients im Netzwerk "anzumelden"
+ * Für das Netwerk werden min. 3 Arduinos mit IR-Link-Modulen benötigt:
+ *
+ * Arduino1: sPSN_Broker.ino
+ * 
+ * Arduino2: sPSN_PongTester.ino -> fragt Clients ab
+ * 
+ * Arduino3: sPSN_PingTest.ino -> reagiert auf PongTester
+ * 
+ *date:  01.12.2021
+ */
+
+#include "Arduino.h"
+
+#include "SoftwareSerial.h"
+#include "didacticNet.h"
+
+//lege Geschwindigkeit für serielle Schnittstellen fest
+#define SERIAL_BAUD 2400
+
+//HIER CLIENT_ZAHL ANPASSEN
+//*******************************
+#define MAX_NR_CLIENTS 15
+//*******************************
+
+//lege Pins für SoftwareSerielle Schnittstelle fest
+// Rx = 10 -> Empfänger | Tx = 11 -> Sender
+SoftwareSerial sSerial(10, 11);
+
+//Erzeuge Client-Instanz
+DidacticPSNetClient psnClient;
+
+//Arrays für Empfangs- und Sende Topic
+char topicSub[MAX_LEN_TOPICS] = "";
+char topicPub[MAX_LEN_TOPICS] = "";
+
+char payloadSend[] = "Pong";
+
+bool ledState = true;
+
+void myCallback(char* mTopic, int mToLength, char* mData, int mDaLength) {
+  Serial.println(mTopic);
+  //reply pong
+  strcpy(topicPub, mTopic);
+  if (!strcmp(mData, "Ping")) {
+    Serial.print(" ");
+    Serial.println(mTopic);
+    psnClient.publish(topicPub, payloadSend);
+  }
+}
+
+
+void setup() {
+  //Starte Serielle Schnittstelle (zum PC)
+  Serial.begin(SERIAL_BAUD);
+  delay(2000);
+
+  Serial.print("\nSearching for ");
+  Serial.print(MAX_NR_CLIENTS);
+  Serial.println(" sPSNet-Clients");
+
+  //Starte SoftwareSerielle Schnittstelle (zu IR-Link-Modulen)
+  sSerial.begin(SERIAL_BAUD);
+
+  pinMode(LED_BUILTIN, OUTPUT);
+  digitalWrite(LED_BUILTIN, LOW);
+
+  psnClient.begin(sSerial, myCallback);
+
+  //psnClient.subscribe("*");
+  Serial.println("Topics: ");
+  for (int clientNr = 0; clientNr < MAX_NR_CLIENTS; ++clientNr) {
+    sprintf(topicSub, "%02d", clientNr);
+    psnClient.subscribe(topicSub);
+    while (!psnClient.handleNetwork());
+    Serial.print(topicSub);
+    Serial.print(" ");
+  }
+
+  Serial.println("\n\nReady for Clients...");
+
+}
+
+void loop() {
+  //Verarbeiten der Daten, prüfen ob Netzwerk frei und versenden der Daten
+  psnClient.handleNetwork();
+}
diff --git a/examples/sPSN_Server/sPSN_Server.ino b/examples/sPSN_Server/sPSN_Server.ino
deleted file mode 100644
index 849fcb72e38200df68acac04fe11957d251b610e..0000000000000000000000000000000000000000
--- a/examples/sPSN_Server/sPSN_Server.ino
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- *file:  sPSN_Server.ino
- *author:  letsgoING -> info@letsgoing.de
- *
- *description:
- * Dieses Programm ist ein Teil eines Beispiels für ein einfaches Pub-Sub-Netzwerk.
- *
- * Für ein Sensor-Netwerk werden 3 Arduinos mit IR-Link-Modulen benötigt:
- * Arduino1: sPSN_Broker.ino (dieses Programm)
- *           - IR-Sender an Pin 11 IR-Empfänger an Pin10
- * Arduino2: sPSN_Client1.ino
- *           - IR-Sender an Pin 11 IR-Empfänger an Pin10
- *           - Taster an Pin2
- *           - LED an Pin9
- * Arduino3: sPSN_Client2.ino
- *           - IR-Sender an Pin 11 IR-Empfänger an Pin10
- *           - Poti an PinA0
- *           - LED an Pin9
- *
- * Für ein Chat-Netzwerk werden mindestens 3 Arduinos benötigt:
- * Arduino1:   sPSN_Server.ino (dieses Programm)
- *            - IR-Sender an Pin 11 IR-Empfänger an Pin10
- * Arduino2-n: sPSN_Chat.ino
- *            - IR-Sender an Pin 11 IR-Empfänger an Pin10
- *
- *date:  14.12.2020
- *version: 1.0
- */
-
-#include "SoftwareSerial.h"
-#include "didacticNet.h"
-
-//lege Geschwindigkeit für serielle Schnittstellen fest
-#define SERIAL_BAUD 2400
-
-//lege Pins für SoftwareSerielle Schnittstelle fest
-// Rx = 10 -> Empfänger | Tx = 11 -> Sender
-SoftwareSerial sSerial(10, 11);
-
-//Erzeuge Server-Instanz
-didacticPSNetServer psnBroker;
-
-void setup() {
-  //Starte Serielle Schnittstelle (zum PC)
-  Serial.begin(SERIAL_BAUD);
-
-  //Starte SoftwareSerielle Schnittstelle (zu IR-Link-Modulen)
-  sSerial.begin(SERIAL_BAUD);
-
-  //Lege fest welche Serielle Schnittstelle für sPSN verwendet werden soll
-  //psnBroker.setStream(sSerial);
-  psnClient.begin(sSerial);
-}
-
-void loop() {
-  //hier verarbeitet der Server alle Daten
-  psnBroker.handleNetwork();
-}
diff --git a/keywords.txt b/keywords.txt
index 65ad9e5f2a21b798d29803b614b1849510abd967..542b41df93aae8db0b8510a1d1aca8d2970ec1eb 100644
--- a/keywords.txt
+++ b/keywords.txt
@@ -5,10 +5,13 @@
 #######################################
 # Datatypes (KEYWORD1)
 #######################################
-
-didacticPSNet		KEYWORD1
-didacticPSNetBroker	KEYWORD1
-didacticPSNetClient	KEYWORD1
+DidacticPSNet	KEYWORD1
+DidacticPSNetBroker	KEYWORD1
+DidacticPSNetClient	KEYWORD1
+EdgeDetector	KEYWORD1
+ChangeDetector	KEYWORD1
+UnblockingTimer	KEYWORD1
+SerialReader	KEYWORD1
 
 #######################################
 # Methods and Functions (KEYWORD2)
@@ -17,17 +20,22 @@ setCallback	KEYWORD2
 setStream	KEYWORD2
 handleNetwork	KEYWORD2
 isDataToSend	KEYWORD2
+setInterval	KEYWORD2
 
 publish	KEYWORD2
+publishOnChange	KEYWORD2
 subscribe	KEYWORD2
 unsubscribe	KEYWORD2
 
+timeElapsed	KEYWORD2
+readSerialData	KEYWORD2
+
 #######################################
 # Constants (LITERAL1)
 #######################################
-MSG_PRELIMITER		LITERAL1
-MSG_DELIMITER		LITERAL1
-MSG_SEPARATOR		LITERAL1
+MSG_PRELIMITER	LITERAL1
+MSG_DELIMITER	LITERAL1
+MSG_SEPARATOR	LITERAL1
 
 MSG_PUBLISH		LITERAL1
 MSG_SUBSCRIBE		LITERAL1
@@ -37,4 +45,12 @@ MSG_TOPIC_MULTI	LITERAL1
 MAX_NR_TOPICS_CLIENT	LITERAL1
 MAX_NR_TOPICS_BROKER	LITERAL1
 MAX_LEN_TOPICS		LITERAL1
-MAX_LEN_DATA		LITERAL1
+MAX_LEN_PAYLOAD	LITERAL1
+
+DN_ASCII_CR	LITERAL1
+DN_ASCII_NL	LITERAL1
+
+DN_PUBLISH_SUCCESSULL	LITERAL1
+DN_ERROR_NO_ERROR	LITERAL1
+DN_ERROR_TOPIC_LEN	LITERAL1
+DN_ERROR_PAYLOAD_LEN	LITERAL1
\ No newline at end of file
diff --git a/library.properties b/library.properties
index fb194340583c56434140063784b0e64c7c172c3e..1333af140fa1c79bf7ca58beab746abef135e8c1 100644
--- a/library.properties
+++ b/library.properties
@@ -1,9 +1,9 @@
 name=didacticNetwork
-version=0.2
+version=0.9
 author=letsgoING
-maintainer=letsgoING <info@letsgoing.org>
+maintainer=letsgoING <https://letsgoing.org>
 sentence=Library for implementing didactic reduced networks on Arduino boards.
 category=Communication
 paragraph=Library for implementing networks on Arduino boards. The functionalities correspond to state of the art technologies, which are didactically reduced.
 url=https://gitlab.reutlingen-university.de/letsgoing/libraries/didacticnetwork
-includes=didacticNetwork.h
+includes=didacticNet.h
diff --git a/src/didacticNet.cpp b/src/didacticNet.cpp
index 67fc6c552a253b1d8e3b8626c6a339b2ea53459f..80a9f5d3c63849e5d552e052b0ffd9f9af3ac228 100644
--- a/src/didacticNet.cpp
+++ b/src/didacticNet.cpp
@@ -8,34 +8,33 @@
 #include "Arduino.h"
 #include "didacticNet.h"
 
-
 //**************************************************************************
-//BASIC
+//ROOT
 //**************************************************************************
-didacticPSNet::didacticPSNet(){}
+DidacticPSNet::DidacticPSNet(){}
 
-didacticPSNet::~didacticPSNet(){}
+DidacticPSNet::~DidacticPSNet(){}
 
-void didacticPSNet::begin(Stream& _port){
+void DidacticPSNet::begin(Stream& _port){
   setStream(_port);
 }
 
-void didacticPSNet::begin(Stream& _port, PSNET_CALLBACK_SIGNATURE){
+void DidacticPSNet::begin(Stream& _port, PSNET_CALLBACK_SIGNATURE){
   setStream(_port);
   setCallback(callback);
 }
 
-didacticPSNet& didacticPSNet::setCallback(PSNET_CALLBACK_SIGNATURE){
+DidacticPSNet& DidacticPSNet::setCallback(PSNET_CALLBACK_SIGNATURE){
     this->callback = callback;
     return *this;
 }
 
-void didacticPSNet::setStream(Stream& stream){
+void DidacticPSNet::setStream(Stream& stream){
     _port = &stream;
 }
 
-bool didacticPSNet::handleNetwork(){
-  if(_waitingTime <= millis()){
+bool DidacticPSNet::handleNetwork(){
+  //if(_waitingTime <= millis()){
   	if(checkData()){
   		if(recieveData()){
         //Serial.print("Message filter: ");Serial.println(_readBufferMessage[1]);
@@ -44,65 +43,75 @@ bool didacticPSNet::handleNetwork(){
           handleData();
   			}
   		}
-  		_waitingTime = millis()+ random(CSMA_MIN_DELAY_MS, CSMA_MAX_DELAY_MS);
+  		_waitingTimeCSMA = millis()+ random(CSMA_MIN_DELAY_MS, CSMA_MAX_DELAY_MS);
   	}
-  	else if(_dataToSend){
-  		//send data to network
+  	//else if(_dataToSend){
+    if(_dataToSend && _waitingTimeSend <= millis() && _waitingTimeCSMA <= millis()){
+      //send data to network
       //TODO: test added CSMA_CHECKDELAY + 2nd checkData()
       unsigned long delayStartTime = micros();
       while(micros() < delayStartTime + CSMA_CHECK_DELAY_US);
       //delayMicroseconds(CSMA_CHECK_DELAY_US); //removed: blocking SoftSerial-interrupts
       if(!checkData()){
-      	if(!sendData()){
-    			return false;
-    		}
+        if(!sendData()){
+          return false;
+        }
         else{
           _dataToSend = false;
-          _waitingTime = millis()+ random(CSMA_MID_DELAY_MS, CSMA_MAX_DELAY_MS);
+          //_waitingTime = millis()+ random(CSMA_MID_DELAY_MS, CSMA_MAX_DELAY_MS);
+          _waitingTimeSend = millis() + _intervalTime;//random(CSMA_MID_DELAY_MS, CSMA_MAX_DELAY_MS);
         }
       }
-  	}
-  }
+    }
+  //}
 	return true;
 }
 
-bool didacticPSNet::isDataToSend(){
+bool DidacticPSNet::isDataToSend(){
   return _dataToSend;
 }
 
-bool didacticPSNet::sendData(){
+bool DidacticPSNet::sendData(){
 	int counter = 0;
-	while(_sendBufferMessage[counter]!= '\0'){
+  bool messageSent = false;
+	while(!messageSent){
+    if(counter >= MAX_LEN_TOPICS + MAX_LEN_PAYLOAD + LEN_OVERHEAD - 1){
+      //TODO: check!!!
+      _sendBufferMessage[counter] = MSG_DELIMITER; //cut message and stop sending
+      messageSent = true;
+		} 
+    else if(_sendBufferMessage[counter] == MSG_DELIMITER){
+      messageSent = true;
+    }
+
 		_port->write(_sendBufferMessage[counter]);
 		counter++;
-		if(counter > MAX_LEN_TOPICS + MAX_LEN_DATA + 5){
-		return false;
-		}
 	}
 	return true;
 }
 
-int didacticPSNet::extractData(int startCounter, int maxLength, char* buffer, char limiter){
+int DidacticPSNet::extractData(int startCounter, int maxLength, char* buffer, char limiter){
 	int counter = startCounter;
 	while(_readBufferMessage[counter]!= limiter){
 		buffer[counter-startCounter] = _readBufferMessage[counter];
 		counter++;
 		if((counter-startCounter) > maxLength){
-		return -1;
+      counter--;
+      break; //if > maxLenght -> leave while and return
 		}
 	}
 	buffer[counter-startCounter] = '\0';
-	return counter-startCounter; //length of Topic
+	return counter-startCounter; //length
 }
 
-int didacticPSNet::checkData(){
+int DidacticPSNet::checkData(){
 	return (int)_port->available();
 }
 
-bool  didacticPSNet::recieveData() {
+bool  DidacticPSNet::recieveData() {
 	static int msgCounter = 0;
 	static int topicCounter = 0;
-	static int dataCounter = 0;
+	static int payloadCounter = 0;
 	//if(msgCounter == NULL){	msgCounter = 0;	}
 	//if(topicCounter == NULL){ topicCounter = 0; }
 	//if(dataCounter == NULL){ dataCounter = 0; }
@@ -111,7 +120,7 @@ bool  didacticPSNet::recieveData() {
 		if (localBuffer == MSG_PRELIMITER) {
 			msgCounter = 0;
 			topicCounter = 0;
-			dataCounter = 0;
+			payloadCounter = 0;
 			_readBufferMessage[msgCounter] = localBuffer;
     }
 		else if (localBuffer == MSG_DELIMITER && _readBufferMessage[0] == MSG_PRELIMITER) {
@@ -134,112 +143,99 @@ bool  didacticPSNet::recieveData() {
 	return false;
 }
 
+		void  DidacticPSNet::setInterval(long intervalTime){
+      _intervalTime = intervalTime;
+    }
+
+
 //**************************************************************************
 // CLIENT
 //**************************************************************************
-didacticPSNetClient::didacticPSNetClient(){}
+DidacticPSNetClient::DidacticPSNetClient(){
+  _intervalTime = INTERVAL_CLIENT;
+}
 
-didacticPSNetClient::~didacticPSNetClient(){}
+DidacticPSNetClient::~DidacticPSNetClient(){}
 
-bool didacticPSNetClient::publish(char* topic,  char* data){
-	int topicLength =  strlen(topic);
-	int dataLength = strlen(data);
-	_sendBufferMessage[0] = MSG_PRELIMITER;
+int DidacticPSNetClient::publish(char* topic,  char* payload){
+	return publish(topic, strlen(topic), payload, strlen(payload));
+}
+
+int DidacticPSNetClient::publish(char* topic, int topicLength, char* payload , int payloadLength){
+	int error = DN_PUBLISH_SUCCESSULL;
+  
+  _sendBufferMessage[0] = MSG_PRELIMITER;
 	_sendBufferMessage[1] = MSG_PUBLISH;
 	_sendBufferMessage[2+topicLength] = MSG_SEPARATOR;
-	_sendBufferMessage[2+topicLength+1+dataLength] = MSG_DELIMITER;
-	_sendBufferMessage[2+topicLength+1+dataLength+1] = '\0';
+	_sendBufferMessage[2+topicLength+1+payloadLength] = MSG_DELIMITER;
+	_sendBufferMessage[2+topicLength+1+payloadLength+1] = '\0';
 
-	if(topicLength <= MAX_LEN_TOPICS){
-		for(int i = 0; i < topicLength; i++){
+	//TODO: check
+  if(topicLength > MAX_LEN_TOPICS){
+    topicLength = MAX_LEN_TOPICS;
+    error += DN_ERROR_TOPIC_LEN;
+  }
+  if(payloadLength > MAX_LEN_PAYLOAD){
+    payloadLength = MAX_LEN_PAYLOAD;
+    error += DN_ERROR_PAYLOAD_LEN;
+  }
+
+  for(int i = 0; i < topicLength; i++){
 			_sendBufferMessage[2+i] = topic[i];
 		}
-	}else {
-    _dataToSend = false;
-		return false;
-	}
-	if(dataLength <= MAX_LEN_DATA){
-		for(int i = 0; i < dataLength; i++){
-			_sendBufferMessage[2+topicLength+1+i] = data[i];
+  for(int i = 0; i < payloadLength; i++){
+			_sendBufferMessage[2+topicLength+1+i] = payload[i];
 		}
-	}else {
-    _dataToSend = false;
-		return false;
-	}
+
   _dataToSend = true;
-	return true;
+	return error;
 }
 
-bool didacticPSNetClient::publish(char* topic, int topicLength, char* data , int dataLength){
-	_sendBufferMessage[0] = MSG_PRELIMITER;
-	_sendBufferMessage[1] = MSG_PUBLISH;
-	_sendBufferMessage[2+topicLength] = MSG_SEPARATOR;
-	_sendBufferMessage[2+topicLength+1+dataLength] = MSG_DELIMITER;
-	_sendBufferMessage[2+topicLength+1+dataLength+1] = '\0';
+//TODO: TEST TEST TEST
+int DidacticPSNetClient::publish(char* topic,  int data){
+  char sendPayload[MAX_LEN_PAYLOAD];
+  itoa(data, sendPayload, 10);
 
-	if(topicLength <= MAX_LEN_TOPICS){
-		for(int i = 0; i < topicLength; i++){
-			_sendBufferMessage[2+i] = topic[i];
-		}
-	}else {
-    _dataToSend = false;
-		return false;
-	}
-	if(dataLength <= MAX_LEN_DATA){
-		for(int i = 0; i < dataLength; i++){
-			_sendBufferMessage[2+topicLength+1+i] = data[i];
-		}
-	}else {
-    _dataToSend = false;
-		return false;
-	}
-  _dataToSend = true;
-	return true;
+	return publish(topic, sendPayload);
 }
 
-bool didacticPSNetClient::subscribe(char* topic){
-  int topicLength = strlen(topic);
-  _sendBufferMessage[0] = MSG_PRELIMITER;
-	_sendBufferMessage[1] = MSG_SUBSCRIBE;
-	_sendBufferMessage[2+topicLength] = MSG_DELIMITER;
+int DidacticPSNetClient::publish(char* topic,  bool data){
+  char sendPayload[2];
+  itoa(data, sendPayload, 10);
 
-  int topicNumber = getTopicNr(topic);
+	return publish(topic, sendPayload);
+}
 
-  if(topicNumber < 0){
-    topicNumber = getFreeTopicNr();
-    if(topicNumber < 0){
-      topicNumber = 0;
+int DidacticPSNetClient::publishOnChange(char* topic, bool input){
+  if(!_dataToSend){
+    if(eDetector.edgeDetected(input)){
+      return publish(topic, input);
     }
-    if( topicLength <= MAX_LEN_TOPICS){
-  		for(int i = 0; i < topicLength; i++){
-  			_topic[topicNumber][i] = topic[i];
-        _sendBufferMessage[2+i]= topic[i];
-  		}
-      _topic[topicNumber][topicLength] = '\0';
-      _sendBufferMessage[2+topicLength+1]= '\0';
-      _dataToSend = true;
-  	}
-  	else {
-      _dataToSend = false;
-  		return false;
-  	}
-  }
-  else{
-    if( topicLength <= MAX_LEN_TOPICS){
-  		for(int i = 0; i < topicLength; i++){
-        _sendBufferMessage[2+i]= topic[i];
-  		}
-      _sendBufferMessage[2+topicLength+1]= '\0';
-      _dataToSend = true;
-  	}
   }
-  while(_dataToSend){
-    handleNetwork();
+  return DN_ERROR_NO_ERROR;
+}
+
+int DidacticPSNetClient::publishOnChange(char* topic, int input, int threshold){
+  if(!_dataToSend){
+    if(cDetector.valueChanged(input, threshold)){
+      return publish(topic, input);
+    }
   }
-	return true;
+  return DN_ERROR_NO_ERROR;
 }
 
-bool didacticPSNetClient::subscribe(char* topic, int topicLength){
+int DidacticPSNetClient::subscribe(char* topic){
+	return subscribe(topic, strlen(topic));
+}
+
+int DidacticPSNetClient::subscribe(char* topic, int topicLength){
+   int error = DN_ERROR_NO_ERROR;
+
+   if( topicLength > MAX_LEN_TOPICS){
+    topicLength = MAX_LEN_TOPICS;
+    error = DN_ERROR_TOPIC_LEN;
+    }
+
   _sendBufferMessage[0] = MSG_PRELIMITER;
 	_sendBufferMessage[1] = MSG_SUBSCRIBE;
 	_sendBufferMessage[2+topicLength] = MSG_DELIMITER;
@@ -251,7 +247,6 @@ bool didacticPSNetClient::subscribe(char* topic, int topicLength){
     if(topicNumber < 0){
       topicNumber = 0;
     }
-    if( topicLength <= MAX_LEN_TOPICS){
   		for(int i = 0; i < topicLength; i++){
   			_topic[topicNumber][i] = topic[i];
         _sendBufferMessage[2+i]= topic[i];
@@ -259,39 +254,26 @@ bool didacticPSNetClient::subscribe(char* topic, int topicLength){
       _topic[topicNumber][topicLength] = '\0';
       _sendBufferMessage[2+topicLength+1]= '\0';
       _dataToSend = true;
-  	}
-  	else {
-      _dataToSend = false;
-  		return false;
-  	}
   }
   else{
-    if( topicLength <= MAX_LEN_TOPICS){
   		for(int i = 0; i < topicLength; i++){
         _sendBufferMessage[2+i]= topic[i];
   		}
       _sendBufferMessage[2+topicLength+1]= '\0';
       _dataToSend = true;
-  	}
   }
   while(_dataToSend){
     handleNetwork();
   }
-	return true;
+	return error;
 }
 
 
-bool didacticPSNetClient::unsubscribe(char* topic){
-  int topicNumber = getTopicNr(topic);
-  int topicLength = strlen(topic);
-  if(topicNumber >= 0){
-    _topic[topicNumber][0]='\0';
-    return true;
-  }
-  return false;
+bool DidacticPSNetClient::unsubscribe(char* topic){
+  return unsubscribe(topic, strlen(topic));
 }
 
-bool didacticPSNetClient::unsubscribe(char* topic, int topicLength){
+bool DidacticPSNetClient::unsubscribe(char* topic, int topicLength){
   int topicNumber = getTopicNr(topic);
   if(topicNumber >= 0){
     _topic[topicNumber][0]='\0';
@@ -300,41 +282,42 @@ bool didacticPSNetClient::unsubscribe(char* topic, int topicLength){
   return false;
 }
 
-bool didacticPSNetClient::getMessageFilter(char messageType){
+bool DidacticPSNetClient::getMessageFilter(char messageType){
   return messageType == MSG_UPDATE;
 }
 
-bool didacticPSNetClient::saveData(char* buffer, int position){
-  strcpy(_data[position], buffer);
+bool DidacticPSNetClient::savePayload(char* buffer, int position){
+  strcpy(_payload[position], buffer);
   return true;
 }
 
-bool didacticPSNetClient::handleData(){
+bool DidacticPSNetClient::handleData(){
   int currentTopicNr = 0;
   int topicLength = 0;
-  int dataLength = 0;
+  int payloadLength = 0;
   topicLength = extractData(2, MAX_LEN_TOPICS, _bufferTopic, MSG_SEPARATOR);
   if(topicLength > 0){
     currentTopicNr = getTopicNr(_bufferTopic);
-    dataLength  = extractData(topicLength+3, MAX_LEN_DATA, _bufferData, MSG_DELIMITER);
+    payloadLength  = extractData(topicLength+3, MAX_LEN_PAYLOAD, _bufferPayload, MSG_DELIMITER);
     if( currentTopicNr >= 0){
-      saveData( _bufferData, currentTopicNr);
-      callback(_topic[currentTopicNr], topicLength, _data[currentTopicNr], dataLength);
+      savePayload( _bufferPayload, currentTopicNr);
+      //callback(_topic[currentTopicNr], topicLength, _payload[currentTopicNr], payloadLength);
+      callback(_bufferTopic, topicLength, _bufferPayload, payloadLength);
     }
   }
   return true;
 }
 
-int didacticPSNetClient::getTopicNr(char* topic){
+int DidacticPSNetClient::getTopicNr(char* topic){
 	for (int i = 0; i < MAX_NR_TOPICS_CLIENT; i++) {
-    if (strcmp(_topic[i], topic) == 0) {
+    if (strcmp(_topic[i], topic) == 0 || _topic[i][0] == MSG_TOPIC_MULTI) { //TODO: check ... or equal MSG_TOPIC_MULTI
       return i;
 		}
 	}
  return -1;
 }
 
-int didacticPSNetClient::getFreeTopicNr() {
+int DidacticPSNetClient::getFreeTopicNr() {
   for (int i = 0; i < MAX_NR_TOPICS_CLIENT; i++) {
     if (strcmp(_topic[i], "") == 0) {
       return i;
@@ -347,28 +330,30 @@ int didacticPSNetClient::getFreeTopicNr() {
 //**************************************************************************
 //Broker
 //**************************************************************************
-didacticPSNetBroker::didacticPSNetBroker(){}
+DidacticPSNetBroker::DidacticPSNetBroker(){
+    _intervalTime = INTERVAL_BROKER;
+}
 
-didacticPSNetBroker::~didacticPSNetBroker(){}
+DidacticPSNetBroker::~DidacticPSNetBroker(){}
 
 
-bool didacticPSNetBroker::getMessageFilter(char messageType){
+bool DidacticPSNetBroker::getMessageFilter(char messageType){
   return (messageType == MSG_PUBLISH || messageType == MSG_SUBSCRIBE);
 }
 
-bool didacticPSNetBroker::saveData(char* buffer, int position){
+bool DidacticPSNetBroker::savePayload(char* buffer, int position){
   strcpy(_data[position], buffer);
   return true;
 }
 
-void didacticPSNetBroker::writeDataToTopic(int topicNumber, char* usedTopic, char* newData) {
+void DidacticPSNetBroker::writeDataToTopic(int topicNumber, char* usedTopic, char* newData) {
     if(strcmp(_topic[topicNumber], "") == 0){
       strcpy(_topic[topicNumber], usedTopic);
     }
       strcpy(_data[topicNumber], newData);
 }
 
-bool didacticPSNetBroker::handleData(){
+bool DidacticPSNetBroker::handleData(){
   int currentTopicNr = 0;
   int topicLength = 0;
   int dataLength = 0;
@@ -376,9 +361,9 @@ bool didacticPSNetBroker::handleData(){
     topicLength = extractData(2, MAX_LEN_TOPICS, _bufferTopic, MSG_SEPARATOR);
     if(topicLength > 0){
       currentTopicNr = getTopicNr(_bufferTopic);
-      dataLength  = extractData(topicLength+3, MAX_LEN_DATA, _bufferData, MSG_DELIMITER);
+      dataLength  = extractData(topicLength+3, MAX_LEN_PAYLOAD, _bufferPayload, MSG_DELIMITER);
       if( currentTopicNr >= 0){
-        writeDataToTopic(currentTopicNr, _bufferTopic, _bufferData);
+        writeDataToTopic(currentTopicNr, _bufferTopic, _bufferPayload);
         update(_topic[currentTopicNr], topicLength, _data[currentTopicNr], dataLength);
       }
     }
@@ -395,7 +380,7 @@ bool didacticPSNetBroker::handleData(){
 return true;
 }
 
-bool didacticPSNetBroker::update(char* topic, int topicLength, char* data , int dataLength){
+bool DidacticPSNetBroker::update(char* topic, int topicLength, char* data , int dataLength){
 	_sendBufferMessage[0] = MSG_PRELIMITER;
 	_sendBufferMessage[1] = MSG_UPDATE;
 	_sendBufferMessage[2+topicLength] = MSG_SEPARATOR;
@@ -410,7 +395,7 @@ bool didacticPSNetBroker::update(char* topic, int topicLength, char* data , int
     _dataToSend = false;
 		return false;
 	}
-	if(dataLength <= MAX_LEN_DATA){
+	if(dataLength <= MAX_LEN_PAYLOAD){
 		for(int i = 0; i < dataLength; i++){
 			_sendBufferMessage[2+topicLength+1+i] = data[i];
 		}
@@ -422,7 +407,7 @@ bool didacticPSNetBroker::update(char* topic, int topicLength, char* data , int
 	return true;
 }
 
-int didacticPSNetBroker::getTopicNr(char* topic){
+int DidacticPSNetBroker::getTopicNr(char* topic){
 	for (int i = 0; i < MAX_NR_TOPICS_BROKER; i++) {
   if (strcmp(_topic[i], topic) == 0) {
       return i;
@@ -431,7 +416,7 @@ int didacticPSNetBroker::getTopicNr(char* topic){
  return	getFreeTopicNr();
 }
 
-int didacticPSNetBroker::getFreeTopicNr() {
+int DidacticPSNetBroker::getFreeTopicNr() {
   for (int i = 0; i < MAX_NR_TOPICS_BROKER; i++) {
     if (strcmp(_topic[i], "") == 0) {
       return i;
@@ -439,3 +424,77 @@ int didacticPSNetBroker::getFreeTopicNr() {
   }
   return -1;
 }
+
+
+//**************************************************************************
+//LITTLE HELPERS FOR CLIENTS ;-)
+//*************************************************************************
+
+EdgeDetector::EdgeDetector(){};
+EdgeDetector::~EdgeDetector(){};
+
+int EdgeDetector::edgeDetected(bool currentState){
+  static bool lastState = false;
+  int edEdge = 0;
+
+  if(currentState && !lastState){
+    edEdge = RISING;
+  }
+  else if(!currentState && lastState){
+    edEdge = FALLING;
+  }
+  lastState = currentState;
+  return edEdge;
+}
+
+ChangeDetector::ChangeDetector(){}
+ChangeDetector::~ChangeDetector(){}
+
+bool ChangeDetector::valueChanged(int value, int threshold){
+  static int lastValue = 0;
+
+  if(abs(value-lastValue) > threshold){
+    lastValue = value;
+    return true;
+  }
+  return false;
+}
+
+
+UnblockingTimer::UnblockingTimer(){}
+UnblockingTimer::~UnblockingTimer(){}
+
+bool UnblockingTimer::timeElapsed(long delayTime){
+  long currentTime = millis();
+
+  if(lastTime + (delayTime-1) < currentTime){
+    lastTime = currentTime;
+    return true;
+  }
+  return false;
+}
+
+SerialReader::SerialReader(){}
+SerialReader::~SerialReader(){}
+
+void SerialReader::begin(Stream& rsStream){
+  _port = &rsStream;
+}
+
+int SerialReader::readSerialData(char* rsDataArray, char rsEndSign) {
+
+  if (_port->available()) {
+    char charBuffer = _port->read();
+    rsDataArray[charCounter] = charBuffer;
+
+    if (charBuffer == rsEndSign) {
+      rsDataArray[charCounter] = '\0';
+      int nrOfChars = charCounter;
+      charCounter = 0;
+      return nrOfChars; 
+    } else {
+      charCounter++;
+    }
+  }
+  return 0;
+}
\ No newline at end of file
diff --git a/src/didacticNet.h b/src/didacticNet.h
index d7057777660f18aaad894d4e512a8d9044bc88aa..41aac4c9419efd6e05adb4e4020877690ff3e36c 100644
--- a/src/didacticNet.h
+++ b/src/didacticNet.h
@@ -1,9 +1,7 @@
-/**************************************************************************/
-/*!
+/**************************************************************************
     @file     didacticNet.h
     @author   anian buehler @ letsgoING
-*/
-/**************************************************************************/
+**************************************************************************/
 
 
 #ifndef _DIDACTICNET_
@@ -20,40 +18,105 @@
 //@ publish   → on publish check topic, then send topic-update
 //? subscribe → subscribe starts update, topic filter @client
 //# update    → update to specific topic Broker to client
-#define MSG_PUBLISH   '@'
-#define MSG_SUBSCRIBE '?'
-#define MSG_UPDATE    '#'
+#define MSG_PUBLISH     '@'
+#define MSG_SUBSCRIBE   '?'
+#define MSG_UPDATE      '#'
+#define MSG_TOPIC_MULTI '*'
 
-#define MSG_TOPIC_MULTI     '*'
+//<@topic|payload>
+#define LEN_OVERHEAD  4
 
 #define CSMA_CHECK_DELAY_US 400
-#define CSMA_MIN_DELAY_MS 10
-#define CSMA_MID_DELAY_MS 20
-#define CSMA_MAX_DELAY_MS 30
+#define CSMA_MIN_DELAY_MS    10
+#define CSMA_MID_DELAY_MS    20
+#define CSMA_MAX_DELAY_MS    30
+
+#define INTERVAL_CLIENT	   500L
+#define INTERVAL_BROKER	     0L
 
 #define MAX_NR_TOPICS_CLIENT  10
 #define MAX_NR_TOPICS_BROKER  20
-#define MAX_LEN_TOPICS 10
-#define MAX_LEN_DATA   20
+#define MAX_LEN_TOPICS 		  10
+#define MAX_LEN_PAYLOAD       20
+
+#define DN_PUBLISH_SUCCESSULL 1
+#define DN_ERROR_NO_ERROR     0
+#define DN_ERROR_TOPIC_LEN   -1
+#define DN_ERROR_PAYLOAD_LEN -2
+
+
+//little helpers
+#define DN_ASCII_CR 13
+#define DN_ASCII_NL 10
+
+
+class EdgeDetector
+{
+	private:
+
+	public:
+		EdgeDetector();
+		~EdgeDetector();
+		int edgeDetected(bool);
+
+};
+
+class ChangeDetector
+{
+	private:
+
+	public:
+		ChangeDetector();
+		~ChangeDetector();
+		bool valueChanged(int, int);
+
+};
+
+class UnblockingTimer
+{
+	private:
+		long lastTime = 0L;
+
+	public:
+		UnblockingTimer();
+		~UnblockingTimer();
+		bool timeElapsed(long);
+
+};
+class SerialReader
+{
+	private:
+		Stream* _port;
+		int charCounter = 0;
+
+	public:
+		SerialReader();
+		~SerialReader();
+		void begin(Stream&);
+		int readSerialData(char*, char);
+
+};
 
-class didacticPSNet
+class DidacticPSNet
 {
 	protected:
 		Stream* _port;
 
 		PSNET_CALLBACK_SIGNATURE;
 
-		char _bufferTopic[MAX_LEN_TOPICS+1] = {0};
-		char _bufferData[MAX_LEN_DATA+1] = {0};
-		char _readBufferMessage[MAX_LEN_TOPICS + MAX_LEN_DATA +4+1];
-		char _sendBufferMessage[MAX_LEN_TOPICS + MAX_LEN_DATA +4+1];
+		char _bufferTopic[MAX_LEN_TOPICS +1] = {0};
+		char _bufferPayload[MAX_LEN_PAYLOAD +1] = {0};
+		char _readBufferMessage[MAX_LEN_TOPICS + MAX_LEN_PAYLOAD + LEN_OVERHEAD +1];
+		char _sendBufferMessage[MAX_LEN_TOPICS + MAX_LEN_PAYLOAD + LEN_OVERHEAD +1];
 
 		bool _dataToSend = false; // int Data to send for queue?
-		unsigned long _waitingTime = 0L;
+		unsigned long _waitingTimeSend = 0L;
+		unsigned long _waitingTimeCSMA = 0L;
+		unsigned long _intervalTime = 0L;
 		int _currentTopicLength = 0;
-		int _currentDataLength  = 0;
+		int _currentPayloadLength  = 0;
 
-		didacticPSNet& setCallback(PSNET_CALLBACK_SIGNATURE);
+		DidacticPSNet& setCallback(PSNET_CALLBACK_SIGNATURE);
 		void setStream(Stream& _port);
 
 		int checkData();
@@ -64,55 +127,64 @@ class didacticPSNet
 		virtual int getTopicNr(char*)=0;
 		virtual int getFreeTopicNr()=0;
 		virtual bool getMessageFilter(char)=0;
-		virtual bool saveData(char*, int)=0;
+		virtual bool savePayload(char*, int)=0;
 		virtual bool handleData()=0;
 
 	public:
-		didacticPSNet();
-		~didacticPSNet();
+		DidacticPSNet();
+		~DidacticPSNet();
 
 		void begin(Stream& _port);
 		void begin(Stream& _port, PSNET_CALLBACK_SIGNATURE);
 		bool handleNetwork();
 		bool isDataToSend();
 
+		void setInterval(long);
+
 };
 
-class didacticPSNetClient : public  didacticPSNet
+class DidacticPSNetClient : public  DidacticPSNet
 {
 	private:
+	EdgeDetector 	eDetector;
+	ChangeDetector  cDetector;
 
 	char _topic[MAX_NR_TOPICS_CLIENT][MAX_LEN_TOPICS+1] = { { 0 } };
-	char _data[MAX_NR_TOPICS_CLIENT][MAX_LEN_DATA+1] = { { 0 } };
+	char _payload[MAX_NR_TOPICS_CLIENT][MAX_LEN_PAYLOAD+1] = { { 0 } };
 
-	bool saveData(char*, int);
+	bool savePayload(char*, int);
 	bool getMessageFilter(char);
 	bool handleData();
 	int getTopicNr(char*);
 	int getFreeTopicNr();
 
-	public:
-	didacticPSNetClient();
-	~didacticPSNetClient();
+	int edgeDetected(bool);
+	bool valueChanged(int, int);
 
-	bool publish(char*, char*);
-	bool publish(char*, int, char*, int);
-	bool subscribe(char*);
-	bool subscribe(char*, int);
+	public:
+	DidacticPSNetClient();
+	~DidacticPSNetClient();
+
+	int publish(char*, char*);
+	int publish(char*, int, char*, int);
+	int publish(char*, int);
+	int publish(char*, bool);
+	int publishOnChange(char*, bool);
+	int publishOnChange(char*, int, int);
+	int subscribe(char*);
+	int subscribe(char*, int);
 	bool unsubscribe(char*);
 	bool unsubscribe(char*, int);
-
 };
 
 
-class didacticPSNetBroker: public  didacticPSNet
+class DidacticPSNetBroker: public  DidacticPSNet
 {
 	private:
-
 	char _topic[MAX_NR_TOPICS_BROKER][MAX_LEN_TOPICS+1] = { { 0 } };
-	char _data[MAX_NR_TOPICS_BROKER][MAX_LEN_DATA+1] = { { 0 } };
+	char _data[MAX_NR_TOPICS_BROKER][MAX_LEN_PAYLOAD+1] = { { 0 } };
 
-	bool saveData(char*, int);
+	bool savePayload(char*, int);
 	bool getMessageFilter(char);
 	void writeDataToTopic(int, char*, char*);
 	bool handleData();
@@ -120,11 +192,13 @@ class didacticPSNetBroker: public  didacticPSNet
 	int getFreeTopicNr();
 
 	public:
-	didacticPSNetBroker();
-	~didacticPSNetBroker();
+	DidacticPSNetBroker();
+	~DidacticPSNetBroker();
 
 	bool update(char*, int, char*, int);
 
 
 };
+
+
 #endif