diff --git a/README.md b/README.md index 86d7ceedad082ebd6cc0c7590d3398055939fe51..50f583eee6fb565f9e2041b9ab73c6ba7d2e8397 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ Bibliothek zur Implementierung von vereinfachten Netzwerken auf Arduino-Boards. Die Funktionalitaeten entsprechen dem Stand der Technik, die Umsetzung ist didaktisch reduziert. -Für eine Nutzung der Bibliothek wird eine drahtlose Schnittstelle benötigt, wleche sich an der Seriellen Schnittstelle betreiben lässt. -Wir empfehlen unsere IR-Link-Module, die Sie selbst herstellen können (Schaltplan und Layout bei uns anfragen - Kontakt über [letsgoING.org](httsp://letsgoING.org) -oder z. B. hier erwerben können: [Hinweise zur Bestellung bei Aisler](#bestellung-bei-aisler). +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). ## Download @@ -33,18 +33,23 @@ https://www.arduino.cc/en/guide/libraries section "Importing a .zip Library" ### Client ```cpp -#Anlegen der Client-Instanz +#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 callback); +void psnClient.begin(Stream& sSerial, fcn clientCallback); // param1: Schnittstelle (Serial | SoftSerial) -// param2: Callback-Funktion +// 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]) @@ -63,30 +68,71 @@ bool psnClient.unsubscribe(char* topic, int length); // param2: Anzahl Zeichen des Topics // return true wenn Daten versendet / false wenn nicht -#Daten unter Topic veroeffentlichen +#Daten unter Topic veroeffentlichen int psnClient.publish(char* topic, char* payload); -// param1: Topic String/char-Array; param2: payload-char-Array +// 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_ERROR_NO_ERROR, +// 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 +// 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 @@ -95,33 +141,51 @@ void psnBroker.begin(Stream& sSerial); #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 - -Wichtiger Hinweis: -Diese Funktionen koennen derzeit nur einmal pro Programm/Client-Instanz eingesetzt werden. -Werden diese an verschiedenen Stellen mit verschiedenen Werten verwendet, werden Werte u. U. ueberschrieben. +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 -int psnClient.edgeDetected(bool currentState); +// 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 -bool psnClient.valueChanged(int currentvalue, int threshold); +// 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 -bool psnClient.timeElapsed(long); +// 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 -int psnClient.readSerialData(Stream&, char*, char); +// 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) @@ -130,7 +194,7 @@ int psnClient.readSerialData(Stream&, char*, char); ### Konstanten -Konstanten aus der Library die fuer die Programmierung genutzt werden und teilweise angepasst werden koennen. +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 @@ -144,7 +208,12 @@ MAX_LEN_PAYLOAD default: 20 MAX_NR_TOPICS_CLIENT default: 5 MAX_NR_TOPICS_BROKER default: 20 -#ERRORs +#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 @@ -164,11 +233,11 @@ MSG_TOPIC_MULTI '*' # Bestellung bei Aisler - Account anlegen -- Link öffnen: [Nachkaufprojekt bei Aisler.net](https://aisler.net/p/NBAQNHFV) +- 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**. +**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 8f8a63f1a3c04cb2eef5db064d17e6ff48b5e1e2..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 1aec4de47f1a6f83355889f44f998605e7bcd017..e2d142d2644ba0defd9a1c018852432d4ff17448 100644 --- a/examples/sPSN_Broker/sPSN_Broker.ino +++ b/examples/sPSN_Broker/sPSN_Broker.ino @@ -38,7 +38,7 @@ SoftwareSerial sSerial(10, 11); //Erzeuge Broker-Instanz -didacticPSNetBroker psnBroker; +DidacticPSNetBroker psnBroker; void setup() { //Starte Serielle Schnittstelle (zum PC) diff --git a/examples/sPSN_Chat/sPSN_Chat.ino b/examples/sPSN_Chat/sPSN_Chat.ino index d480f6a8c5aa0e33a3b6a876ef339ee88449363c..e7b228bf1438dc7015d2dcc90f5f7b8953117193 100644 --- a/examples/sPSN_Chat/sPSN_Chat.ino +++ b/examples/sPSN_Chat/sPSN_Chat.ino @@ -44,7 +44,8 @@ void clientCallback(char* mTopic, int mToLength, char* mData, int mDaLength) { SoftwareSerial sSerial(10, 11); // SoftwareSerial an Rx = Pin10 -> Empfänger | Tx = Pin11 -> Sender -didacticPSNetClient psnClient; //Erzeuge PubSub-Client-Instanz +DidacticPSNetClient psnClient; //Erzeuge PubSub-Client-Instanz +SerialReader sReader; void setup() { @@ -54,6 +55,7 @@ void setup() { sSerial.begin(SERIAL_BAUD); //Starte SoftwareSerielle Schnittstelle (zu IR-Link-Modulen) 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. -> "); @@ -72,7 +74,7 @@ void loop() { psnClient.handleNetwork(); //Verarbeiten der Daten, prüfen ob Netzwerk frei und versenden der Daten - int nrOfAscii = psnClient.readSerialData(Serial, readData, DN_ASCII_CR); //Einlesen der Nutzereingabe am SerialMonitor (Rueckgabewert = Anzahl der gelesenen Zeichen) + 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 @@ -85,7 +87,7 @@ void loop() { 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 '@') + 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) Serial.print("Nachrichten von "); //Ausgabe welches Topic abonniert wurde diff --git a/examples/sPSN_Client1/sPSN_Client1.ino b/examples/sPSN_Client1/sPSN_Client1.ino index 249b4c3ce1446f68cc6187196ff50aa3df39c6df..e17005086f286493089dcf3ca436d9ab92b2147f 100644 --- a/examples/sPSN_Client1/sPSN_Client1.ino +++ b/examples/sPSN_Client1/sPSN_Client1.ino @@ -30,30 +30,31 @@ #define POTI_PIN A0 #define THRESHOLD 10 //Schwellwert für min. Wertänderung -#define SEND_DELAY 500 //Mindestwarezeit zwischen zwei Sendevorgängen -char topicPublish[MAX_LEN_TOPICS] = "potiVal"; //Topic für zu sendende (eigene) Daten -char topicSubscribe[MAX_LEN_TOPICS] = "buttonVal"; //Topic für zu empfangende Daten (von anderem TN) +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}; -boolean newData = false; SoftwareSerial sSerial(10, 11); //Erzeuge SoftwareSerial-Instanz mit Rx = Pin10 -> Empfänger | Tx = Pin11 -> Sender -didacticPSNetClient psnClient; //Erzeuge PubSub-Client-Instanz +DidacticPSNetClient psnClient; //Erzeuge PubSub-Client-Instanz //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.print(" | "); Serial.println(mData); - boolean stateLED = bool(atoi(mData)); //wandle ASCII-Zeichen in Wert - //Alternativ: sscanf(mData, "%d", &stateLED); //wandle ASCII-Zeichen in Wert - Serial.print(stateLED); - digitalWrite(LED_PIN, stateLED); //Setze Ausgang entsprechend dem empfangenen Wert + 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 + } } @@ -75,15 +76,7 @@ void loop() { psnClient.handleNetwork(); //Verarbeiten der Daten, prüfen ob Netzwerk frei und versenden der Daten int currentValue = analogRead(POTI_PIN); //lese Poti ein und speichere Wert - - if(psnClient.valueChanged(currentValue, THRESHOLD)){ - itoa(currentValue, payload, 10); //wandle Wert in ASCII-Zeichen - //Alternativ: sprintf(payload, "%d", currentValue); //wandle Wert in ASCII-Zeichen - newData = true; //Flag: neue Daten zum Senden - } - if(psnClient.timeElapsed(SEND_DELAY) && newData){ //Sende neue Daten wenn Mindestwaretzeit abgelaufen - psnClient.publish(topicPublish, payload); //bereite Topic und Nutzdaten zum senden vor - newData = false; //Flag: keine neuen Daten vorhanden - } + psnClient.publishOnChange(topicPublish, currentValue, THRESHOLD); + } diff --git a/examples/sPSN_Client2/sPSN_Client2.ino b/examples/sPSN_Client2/sPSN_Client2.ino index ad31487990138e20535fad7c15f1ac5950b210e7..5e49f515a0ae66a38edcbd61446f3009e42a0ba3 100644 --- a/examples/sPSN_Client2/sPSN_Client2.ino +++ b/examples/sPSN_Client2/sPSN_Client2.ino @@ -24,12 +24,11 @@ #define SERIAL_BAUD 2400 //lege Geschwindigkeit für serielle Schnittstellen fest #define LED_PIN 5 +#define LED2_PIN 6 #define BUTTON_PIN 2 -#define SEND_DELAY 500 //Mindestwarezeit zwischen zwei Sendevorgängen - -char topicPublish[MAX_LEN_TOPICS] = "buttonVal"; //Topic für zu sendende (eigene) Daten -char topicSubscribe[MAX_LEN_TOPICS] = "potiVal"; //Topic für zu empfangende Daten (von anderem TN) +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 char payload[MAX_LEN_PAYLOAD] = {0}; boolean newData = false; @@ -37,21 +36,24 @@ boolean ledState = false; SoftwareSerial sSerial(10, 11); //Erzeuge SoftwareSerial-Instanz mit Rx = Pin10 -> Empfänger | Tx = Pin11 -> Sender -didacticPSNetClient psnClient; //Erzeuge PubSub-Client-Instanz +DidacticPSNetClient psnClient; //Erzeuge PubSub-Client-Instanz +UnblockingTimer uTimer; //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.print(" | "); Serial.println(mData); - int valueLED = atoi(mData); //wandle ASCII-Zeichen in Wert - valueLED = constrain(map(valueLED, 0, 1023, 0, 255), 0, 255); //passe analogRead-Wert für analogWrite an + int valuePoti = atoi(mData); //wandle ASCII-Zeichen in Wert //Alternativ: sscanf(mData, "%d", &stateLED); //wandle ASCII-Zeichen in Wert - analogWrite(LED_PIN, valueLED); //Setze Ausgang entsprechend dem empfangenen Wert + 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 } @@ -70,17 +72,7 @@ void loop() { psnClient.handleNetwork(); //Verarbeiten der Daten, prüfen ob Netzwerk frei und versenden der Daten - boolean buttonState = digitalRead(BUTTON_PIN); //lese Poti ein und speichere Wert - - if(psnClient.edgeDetected(buttonState) == RISING){ - ledState = !ledState; //Invertiere zu sendenden Wert "LED-Zustand" - itoa(ledState, payload, 10); //wandle Wert in ASCII-Zeichen - //Alternativ: sprintf(payload, "%d", currentValue); //wandle Wert in ASCII-Zeichen - newData = true; //Flag: neue Daten zum Senden - } - if(psnClient.timeElapsed(SEND_DELAY) && newData){ //Sende neue Daten wenn Mindestwaretzeit abgelaufen - psnClient.publish(topicPublish, payload); //bereite Topic und Nutzdaten zum senden vor - newData = false; //Flag: keine neuen Daten vorhanden - } + 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 } diff --git a/examples/sPSN_ClientMinimal/sPSN_ClientMinimal.ino b/examples/sPSN_ClientMinimal/sPSN_ClientMinimal.ino index 0e58d6bb209d2a2497290a1ece8f8f0464317507..1805cb58108e1a730c26dcee0223ef58ced973e2 100644 --- a/examples/sPSN_ClientMinimal/sPSN_ClientMinimal.ino +++ b/examples/sPSN_ClientMinimal/sPSN_ClientMinimal.ino @@ -25,8 +25,8 @@ SoftwareSerial sSerial(10, 11); //Erzeuge SoftwareSerial-Instanz mit Rx = Pin10 -> Empfänger | Tx = Pin11 -> Sender -didacticPSNetClient psnClient; //Erzeuge PubSub-Client-Instanz - +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) { @@ -53,13 +53,8 @@ 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 - - char payload[5]; - itoa(currentValue, payload, 10); - - if(psnClient.timeElapsed(1000)){ //Sende neue Daten wenn Mindestwaretzeit 1 Sekunde abgelaufen - //Hier SENDE-TOPIC ANPASSEN -> default "client1" - psnClient.publish("client1", payload); //bereite Topic und Nutzdaten zum senden vor - } + + //Hier SENDE-TOPIC ANPASSEN -> default "client1" + psnClient.publish("client1", currentValue); } diff --git a/keywords.txt b/keywords.txt index d70dbd25191371f0109951bed444664952040e3d..542b41df93aae8db0b8510a1d1aca8d2970ec1eb 100644 --- a/keywords.txt +++ b/keywords.txt @@ -5,9 +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) @@ -16,13 +20,13 @@ setCallback KEYWORD2 setStream KEYWORD2 handleNetwork KEYWORD2 isDataToSend KEYWORD2 +setInterval KEYWORD2 publish KEYWORD2 +publishOnChange KEYWORD2 subscribe KEYWORD2 unsubscribe KEYWORD2 -edgeDetected KEYWORD2 -valueChanged KEYWORD2 timeElapsed KEYWORD2 readSerialData KEYWORD2 @@ -46,6 +50,7 @@ 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 b103e4391dcb62375688e34d444308578b4aa79b..751f90f5310e978605b0f1e469ce70ca5f8e6dae 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=didacticNetwork -version=0.2 +version=0.9 author=letsgoING maintainer=letsgoING <info@letsgoing.org> sentence=Library for implementing didactic reduced networks on Arduino boards. diff --git a/src/didacticNet.cpp b/src/didacticNet.cpp index 6529e29f65f275139ccda0158965048c4ec2ed56..f14ace21992e70b7d533ffd00d95831966f92b66 100644 --- a/src/didacticNet.cpp +++ b/src/didacticNet.cpp @@ -11,30 +11,30 @@ //************************************************************************** //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]); @@ -45,29 +45,31 @@ bool didacticPSNet::handleNetwork(){ } _waitingTime = millis()+ random(CSMA_MIN_DELAY_MS, CSMA_MAX_DELAY_MS); } - else if(_dataToSend){ - //send data to network + //else if(_dataToSend){ + if(_dataToSend && _waitingTime <= millis()){ + //send data to network //TODO: test added CSMA_CHECKDELAY + 2nd checkData() delayMicroseconds(CSMA_CHECK_DELAY_US); 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); + _waitingTime = 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; bool messageSent = false; while(!messageSent){ @@ -86,7 +88,7 @@ bool didacticPSNet::sendData(){ 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]; @@ -100,11 +102,11 @@ int didacticPSNet::extractData(int startCounter, int maxLength, char* buffer, ch 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 payloadCounter = 0; @@ -139,47 +141,26 @@ bool didacticPSNet::recieveData() { return false; } + void DidacticPSNet::setInterval(long intervalTime){ + _intervalTime = intervalTime; + } + + //************************************************************************** // CLIENT //************************************************************************** -didacticPSNetClient::didacticPSNetClient(){} - -didacticPSNetClient::~didacticPSNetClient(){} - -int didacticPSNetClient::publish(char* topic, char* payload){ - int error = DN_ERROR_NO_ERROR; - - int topicLength = strlen(topic); - int payloadLength = strlen(payload); - _sendBufferMessage[0] = MSG_PRELIMITER; - _sendBufferMessage[1] = MSG_PUBLISH; - _sendBufferMessage[2+topicLength] = MSG_SEPARATOR; - _sendBufferMessage[2+topicLength+1+payloadLength] = MSG_DELIMITER; - _sendBufferMessage[2+topicLength+1+payloadLength+1] = '\0'; - - //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; - } +DidacticPSNetClient::DidacticPSNetClient(){ + _intervalTime = INTERVAL_CLIENT; +} - for(int i = 0; i < topicLength; i++){ - _sendBufferMessage[2+i] = topic[i]; - } - for(int i = 0; i < payloadLength; i++){ - _sendBufferMessage[2+topicLength+1+i] = payload[i]; - } +DidacticPSNetClient::~DidacticPSNetClient(){} - _dataToSend = true; - return error; +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_ERROR_NO_ERROR; +int DidacticPSNetClient::publish(char* topic, int topicLength, char* payload , int payloadLength){ + int error = DN_PUBLISH_SUCCESSULL; _sendBufferMessage[0] = MSG_PRELIMITER; _sendBufferMessage[1] = MSG_PUBLISH; @@ -208,49 +189,44 @@ int didacticPSNetClient::publish(char* topic, int topicLength, char* payload , i return error; } -int didacticPSNetClient::subscribe(char* topic){ - int error = DN_ERROR_NO_ERROR; - - int topicLength = strlen(topic); +//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){ - topicLength = MAX_LEN_TOPICS; - error = DN_ERROR_TOPIC_LEN; - } + return publish(topic, sendPayload); +} - _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); } - 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{ - 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 error; + return DN_ERROR_NO_ERROR; +} + +int DidacticPSNetClient::subscribe(char* topic){ + return subscribe(topic, strlen(topic)); } -int didacticPSNetClient::subscribe(char* topic, int topicLength){ +int DidacticPSNetClient::subscribe(char* topic, int topicLength){ int error = DN_ERROR_NO_ERROR; if( topicLength > MAX_LEN_TOPICS){ @@ -291,17 +267,11 @@ int didacticPSNetClient::subscribe(char* topic, int topicLength){ } -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'; @@ -310,16 +280,16 @@ 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::savePayload(char* buffer, int position){ +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 payloadLength = 0; @@ -335,7 +305,7 @@ bool didacticPSNetClient::handleData(){ 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 || _topic[i][0] == MSG_TOPIC_MULTI) { //TODO: check ... or equal MSG_TOPIC_MULTI return i; @@ -344,7 +314,7 @@ int didacticPSNetClient::getTopicNr(char* topic){ 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; @@ -353,89 +323,34 @@ int didacticPSNetClient::getFreeTopicNr() { return -1; } -//************************************************************************** -//LITTLE HELPERS FOR CLIENTS ;-) -//************************************************************************** -int didacticPSNetClient::edgeDetected(bool edCurrentState){ - static bool edLastState = false; - int edEdge = 0; - - if(edCurrentState && !edLastState){ - edEdge = RISING; - } - else if(!edCurrentState && edLastState){ - edEdge = FALLING; - } - edLastState = edCurrentState; - return edEdge; -} - -bool didacticPSNetClient::valueChanged(int vcValue, int vcThreshold){ - static int vcLastValue = 0; - - if(abs(vcValue-vcLastValue) > vcThreshold){ - vcLastValue = vcValue; - return true; - } - return false; -} - -bool didacticPSNetClient::timeElapsed(long teDelayTime){ - static long teLastTime = 0L; - long currentTime = millis(); - - if(teLastTime + (teDelayTime-1) < currentTime){ - teLastTime = currentTime; - return true; - } - return false; -} - -int didacticPSNetClient::readSerialData(Stream& rsStream, char* rsDataArray, char rsEndSign) { - static int rsCounter = 0; - - if (rsStream.available()) { - char charBuffer = rsStream.read(); - rsDataArray[rsCounter] = charBuffer; - - if (charBuffer == rsEndSign) { - rsDataArray[rsCounter] = '\0'; - int nrOfChars = rsCounter; - rsCounter = 0; - return nrOfChars; - } else { - rsCounter++; - } - } - return 0; -} - //************************************************************************** //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::savePayload(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; @@ -462,7 +377,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; @@ -489,7 +404,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; @@ -498,7 +413,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; @@ -506,3 +421,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 fda76125d25b7ba99a791feecf4b73beec7f4979..596db882857b225191ab1d86fa05712d91df8856 100644 --- a/src/didacticNet.h +++ b/src/didacticNet.h @@ -31,20 +31,73 @@ #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 5 #define MAX_NR_TOPICS_BROKER 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 didacticPSNet + +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 { protected: Stream* _port; @@ -58,10 +111,11 @@ class didacticPSNet bool _dataToSend = false; // int Data to send for queue? unsigned long _waitingTime = 0L; + unsigned long _intervalTime = 0L; int _currentTopicLength = 0; int _currentPayloadLength = 0; - didacticPSNet& setCallback(PSNET_CALLBACK_SIGNATURE); + DidacticPSNet& setCallback(PSNET_CALLBACK_SIGNATURE); void setStream(Stream& _port); int checkData(); @@ -76,19 +130,24 @@ class didacticPSNet 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 _payload[MAX_NR_TOPICS_CLIENT][MAX_LEN_PAYLOAD+1] = { { 0 } }; @@ -98,26 +157,27 @@ class didacticPSNetClient : public didacticPSNet int getTopicNr(char*); int getFreeTopicNr(); + int edgeDetected(bool); + bool valueChanged(int, int); + public: - didacticPSNetClient(); - ~didacticPSNetClient(); + 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); - - //little helpers - int edgeDetected(bool); - bool valueChanged(int, int); - bool timeElapsed(long); - int readSerialData(Stream&, char*, char); }; -class didacticPSNetBroker: public didacticPSNet +class DidacticPSNetBroker: public DidacticPSNet { private: char _topic[MAX_NR_TOPICS_BROKER][MAX_LEN_TOPICS+1] = { { 0 } }; @@ -131,11 +191,13 @@ class didacticPSNetBroker: public didacticPSNet int getFreeTopicNr(); public: - didacticPSNetBroker(); - ~didacticPSNetBroker(); + DidacticPSNetBroker(); + ~DidacticPSNetBroker(); bool update(char*, int, char*, int); }; + + #endif