Skip to content
Snippets Groups Projects
Commit eeae689b authored by Anian Bühler's avatar Anian Bühler
Browse files

added library-files and examples

parent ecb6af9b
No related branches found
No related tags found
No related merge requests found
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "simplePSNet.h"
//#define SERVER
#define CLIENT
#define C5 // C1 C2 C3 C4 C5
#define SERIAL_BAUD 2400
SoftwareSerial sSerial(10, 11);
#ifdef SERVER
simplePSNetServer psnS;
void setup() {
Serial.begin(SERIAL_BAUD);
sSerial.begin(SERIAL_BAUD);
psnS.setStream(sSerial);
}
void loop() {
psnS.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
simplePSNetClient 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
/**
*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.
* Für dieses Chat-Netzwerk werden mindestens 3 Arduinos benötigt:
*
* Arduino1: sPSN_Server.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
* 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.
*
*date: 14.12.2020
*version: 1.0
*/
#include "SoftwareSerial.h"
#include "simplePSNet.h"
//lege Geschwindigkeit für serielle Schnittstellen fest
#define SERIAL_BAUD 2400
unsigned long lastTime = 0L;
bool dataReadDone = false;
//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 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) {
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);
//Erzeuge Client-Instanz
simplePSNetClient psnClient;
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
psnClient.setStream(sSerial);
//Lege Callback-Funktion fest (wird ausgeführt wenn neue Daten ankommen)
psnClient.setCallback(myCallback);
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");
}
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++;
}
}
//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(readData);
Serial.println(" hergestellt");
}
//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");
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);
}
}
dataReadDone = false;
}
}
/**
*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_Server.ino
* - IR-Sender an Pin 11 IR-Empfänger an Pin10
*
* 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
*/
#include "SoftwareSerial.h"
#include "simplePSNet.h"
//lege Geschwindigkeit für serielle Schnittstellen fest
#define SERIAL_BAUD 2400
byte ledPin = 9;
byte potiPin = A0;
int lastValue = 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
//Arrays für Empfangs- und Sende Topic
char topicSub[MAX_LEN_TOPICS] = "buttonVal";
char topicPub[MAX_LEN_TOPICS] = "potiVal";
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);
//Setze Ausgang entsprechend dem gesendeten Wert
digitalWrite(ledPin, (bool)atoi(mData));
}
//lege Pins für SoftwareSerielle Schnittstelle fest
// Rx = 10 -> Empfänger | Tx = 11 -> Sender
SoftwareSerial sSerial(10, 11);
//Erzeuge Client-Instanz
simplePSNetClient 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);
//Starte SoftwareSerielle Schnittstelle (zu IR-Link-Modulen)
sSerial.begin(SERIAL_BAUD);
pinMode(ledPin, OUTPUT);
//Lege fest welche Serielle Schnittstelle für sPSN verwendet werden soll
psnClient.setStream(sSerial);
//Lege Callback-Funktion fest (wird ausgeführt wenn neue Daten ankommen)
psnClient.setCallback(myCallback);
//Lege fest zu welchem Topic Daten empfangen werden sollen
psnClient.subscribe(topicSub);
}
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;
}
}
/**
*file: sPSN_Client2
*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_Server.ino
* - 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 (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
*/
#include "SoftwareSerial.h"
#include "simplePSNet.h"
//lege Geschwindigkeit für serielle Schnittstellen fest
#define SERIAL_BAUD 2400
byte ledPin = 9;
byte buttonPin = 2;
bool lastState = 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
//Arrays für Empfangs- und Sende Topic
char topicSub[MAX_LEN_TOPICS] = {"potiVal"};
char topicPub[MAX_LEN_TOPICS] = {"buttonVal"};
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);
//Setze Ausgang entsprechend dem gesendeten Wert
analogWrite(ledPin, map(atoi(mData), 0, 1023, 0, 255));
}
//lege Pins für SoftwareSerielle Schnittstelle fest
// Rx = 10 -> Empfänger | Tx = 11 -> Sender
SoftwareSerial sSerial(10, 11);
//Erzeuge Client-Instanz
simplePSNetClient 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);
//Starte SoftwareSerielle Schnittstelle (zu IR-Link-Modulen)
sSerial.begin(SERIAL_BAUD);
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
//Lege fest welche Serielle Schnittstelle für sPSN verwendet werden soll
psnClient.setStream(sSerial);
//Lege Callback-Funktion fest (wird ausgeführt wenn neue Daten ankommen)
psnClient.setCallback(myCallback);
//Lege fest zu welchem Topic Daten empfangen werden sollen
psnClient.subscribe(topicSub);
}
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;
}
/**
*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_Server.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 "simplePSNet.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
simplePSNetServer psnServer;
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
psnServer.setStream(sSerial);
}
void loop() {
//hier verarbeitet der Server alle Daten
psnServer.handleNetwork();
}
/**************************************************************************/
/*!
@file simplePSNet.cpp
@author anian buehler @ letsgoING.org
*/
/**************************************************************************/
#include "Arduino.h"
#include "simplePSNet.h"
//**************************************************************************
//BASIC
//**************************************************************************
simplePSNet::simplePSNet(){}
simplePSNet::~simplePSNet(){}
simplePSNet& simplePSNet::setCallback(void(*callback)(char*, int, char*, int)){
this->callback = callback;
return *this;
}
void simplePSNet::setStream(Stream& stream){
_port = &stream;
}
bool simplePSNet::handleNetwork(){
if(_waitingTime <= millis()){
if(checkData()){
if(recieveData()){
//Serial.print("Message filter: ");Serial.println(_readBufferMessage[1]);
//Serial.print("Check Message filter: ");Serial.println(getMessageFilter(_readBufferMessage[1]));
if(getMessageFilter(_readBufferMessage[1])){
handleData();
}
}
_waitingTime = millis()+ random(CSMA_MIN_DELAY_MS, CSMA_MAX_DELAY_MS);
}
else if(_dataToSend){
//send data to network
if(!sendData()){
return false;
}
else{
_dataToSend = false;
_waitingTime = millis()+ random(CSMA_MID_DELAY_MS, CSMA_MAX_DELAY_MS);
}
}
}
return true;
}
bool simplePSNet::isDataToSend(){
return _dataToSend;
}
bool simplePSNet::sendData(){
int counter = 0;
while(_sendBufferMessage[counter]!= '\0'){
_port->write(_sendBufferMessage[counter]);
counter++;
if(counter > MAX_LEN_TOPICS + MAX_LEN_DATA + 5){
return false;
}
}
return true;
}
int simplePSNet::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;
}
}
buffer[counter-startCounter] = '\0';
return counter-startCounter; //length of Topic
}
int simplePSNet::checkData(){
return (int)_port->available();
}
bool simplePSNet::recieveData() {
static int msgCounter = 0;
static int topicCounter = 0;
static int dataCounter = 0;
//if(msgCounter == NULL){ msgCounter = 0; }
//if(topicCounter == NULL){ topicCounter = 0; }
//if(dataCounter == NULL){ dataCounter = 0; }
while (checkData()) {
char localBuffer = _port->read();
if (localBuffer == MSG_PRELIMITER) {
msgCounter = 0;
topicCounter = 0;
dataCounter = 0;
_readBufferMessage[msgCounter] = localBuffer;
}
else if (localBuffer == MSG_DELIMITER && _readBufferMessage[0] == MSG_PRELIMITER) {
msgCounter++;
_readBufferMessage[msgCounter] = localBuffer;
_readBufferMessage[msgCounter+1] = '0';
msgCounter = 0;
return true;
}
else if (localBuffer == MSG_SEPARATOR && _readBufferMessage[0] == MSG_PRELIMITER) {
topicCounter = msgCounter -2;
msgCounter++;
_readBufferMessage[msgCounter] = localBuffer;
}
else if (_readBufferMessage[0] == MSG_PRELIMITER && localBuffer != MSG_DELIMITER) {
msgCounter++;
_readBufferMessage[msgCounter] = localBuffer;
}
}
return false;
}
//**************************************************************************
// CLIENT
//**************************************************************************
simplePSNetClient::simplePSNetClient(){}
simplePSNetClient::~simplePSNetClient(){}
bool simplePSNetClient::publish(char* topic, char* data){
int topicLength = strlen(topic);
int dataLength = strlen(data);
_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';
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;
}
bool simplePSNetClient::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';
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;
}
bool simplePSNetClient::subscribe(char* topic){
int topicLength = strlen(topic);
_sendBufferMessage[0] = MSG_PRELIMITER;
_sendBufferMessage[1] = MSG_SUBSCRIBE;
_sendBufferMessage[2+topicLength] = MSG_DELIMITER;
int topicNumber = getTopicNr(topic);
if(topicNumber < 0){
topicNumber = getFreeTopicNr();
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];
}
_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;
}
bool simplePSNetClient::subscribe(char* topic, int topicLength){
_sendBufferMessage[0] = MSG_PRELIMITER;
_sendBufferMessage[1] = MSG_SUBSCRIBE;
_sendBufferMessage[2+topicLength] = MSG_DELIMITER;
int topicNumber = getTopicNr(topic);
if(topicNumber < 0){
topicNumber = getFreeTopicNr();
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];
}
_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;
}
bool simplePSNetClient::unsubscribe(char* topic){
int topicNumber = getTopicNr(topic);
int topicLength = strlen(topic);
if(topicNumber >= 0){
_topic[topicNumber][0]='\0';
return true;
}
return false;
}
bool simplePSNetClient::unsubscribe(char* topic, int topicLength){
int topicNumber = getTopicNr(topic);
if(topicNumber >= 0){
_topic[topicNumber][0]='\0';
return true;
}
return false;
}
bool simplePSNetClient::getMessageFilter(char messageType){
return messageType == MSG_UPDATE;
}
bool simplePSNetClient::saveData(char* buffer, int position){
strcpy(_data[position], buffer);
return true;
}
bool simplePSNetClient::handleData(){
int currentTopicNr = 0;
int topicLength = 0;
int dataLength = 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);
if( currentTopicNr >= 0){
saveData( _bufferData, currentTopicNr);
callback(_topic[currentTopicNr], topicLength, _data[currentTopicNr], dataLength);
}
}
return true;
}
int simplePSNetClient::getTopicNr(char* topic){
for (int i = 0; i < MAX_NR_TOPICS_CLIENT; i++) {
if (strcmp(_topic[i], topic) == 0) {
return i;
}
}
return -1;
}
int simplePSNetClient::getFreeTopicNr() {
for (int i = 0; i < MAX_NR_TOPICS_CLIENT; i++) {
if (strcmp(_topic[i], "") == 0) {
return i;
}
}
return -1;
}
//**************************************************************************
//SERVER
//**************************************************************************
simplePSNetServer::simplePSNetServer(){}
simplePSNetServer::~simplePSNetServer(){}
bool simplePSNetServer::getMessageFilter(char messageType){
return (messageType == MSG_PUBLISH || messageType == MSG_SUBSCRIBE);
}
bool simplePSNetServer::saveData(char* buffer, int position){
strcpy(_data[position], buffer);
return true;
}
void simplePSNetServer::writeDataToTopic(int topicNumber, char* usedTopic, char* newData) {
if(strcmp(_topic[topicNumber], "") == 0){
strcpy(_topic[topicNumber], usedTopic);
}
strcpy(_data[topicNumber], newData);
}
bool simplePSNetServer::handleData(){
int currentTopicNr = 0;
int topicLength = 0;
int dataLength = 0;
if(_readBufferMessage[1] == MSG_PUBLISH){
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);
if( currentTopicNr >= 0){
writeDataToTopic(currentTopicNr, _bufferTopic, _bufferData);
update(_topic[currentTopicNr], topicLength, _data[currentTopicNr], dataLength);
}
}
}
else if(_readBufferMessage[1] == MSG_SUBSCRIBE){
topicLength = extractData(2, MAX_LEN_TOPICS, _bufferTopic, MSG_DELIMITER);
if(topicLength > 0){
currentTopicNr = getTopicNr(_bufferTopic);
if(currentTopicNr >= 0){
update(_topic[currentTopicNr], strlen(_topic[currentTopicNr]), _data[currentTopicNr], strlen(_data[currentTopicNr]));
}
}
}
return true;
}
bool simplePSNetServer::update(char* topic, int topicLength, char* data , int dataLength){
_sendBufferMessage[0] = MSG_PRELIMITER;
_sendBufferMessage[1] = MSG_UPDATE;
_sendBufferMessage[2+topicLength] = MSG_SEPARATOR;
_sendBufferMessage[2+topicLength+1+dataLength] = MSG_DELIMITER;
_sendBufferMessage[2+topicLength+1+dataLength+1] = '\0';
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;
}
int simplePSNetServer::getTopicNr(char* topic){
for (int i = 0; i < MAX_NR_TOPICS_SERVER; i++) {
if (strcmp(_topic[i], topic) == 0) {
return i;
}
}
return getFreeTopicNr();
}
int simplePSNetServer::getFreeTopicNr() {
for (int i = 0; i < MAX_NR_TOPICS_SERVER; i++) {
if (strcmp(_topic[i], "") == 0) {
return i;
}
}
return -1;
}
/**************************************************************************/
/*!
@file simplePSNet.h
@author anian buehler @ letsgoING
*/
/**************************************************************************/
#ifndef _SIMPLEPSNET_
#define _SIMPLEPSNET_
#include "Arduino.h"
//callback(topic, topicLength, data, dataLength)
#define SPSN_CALLBACK_SIGNATURE void (*callback)(char*, int, char*, int)
#define MSG_PRELIMITER '<'
#define MSG_DELIMITER '>'
#define MSG_SEPARATOR '|'
//@ publish → on publish check topic, then send topic-update
//? subscribe → subscribe starts update, topic filter @client
//# update → update to specific topic server to client
#define MSG_PUBLISH '@'
#define MSG_SUBSCRIBE '?'
#define MSG_UPDATE '#'
#define MSG_TOPIC_MULTI '*'
#define CSMA_CHECK_DELAY_US 400 //unused?
#define CSMA_MIN_DELAY_MS 10
#define CSMA_MID_DELAY_MS 20
#define CSMA_MAX_DELAY_MS 30
#define MAX_NR_TOPICS_CLIENT 5
#define MAX_NR_TOPICS_SERVER 20
#define MAX_LEN_TOPICS 10
#define MAX_LEN_DATA 20
class simplePSNet
{
protected:
Stream* _port;
SPSN_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];
bool _dataToSend = false; // int Data to send for queue?
unsigned long _waitingTime = 0L;
int _currentTopicLength = 0;
int _currentDataLength = 0;
int checkData();
bool recieveData();
bool sendData();
int extractData(int, int, char*, char);
void writeDataToTopic(char*, char*);
virtual int getTopicNr(char*)=0;
virtual int getFreeTopicNr()=0;
virtual bool getMessageFilter(char)=0;
virtual bool saveData(char*, int)=0;
virtual bool handleData()=0;
public:
simplePSNet();
~simplePSNet();
simplePSNet& setCallback(SPSN_CALLBACK_SIGNATURE);
void setStream(Stream& _port);
bool handleNetwork();
bool isDataToSend();
};
class simplePSNetClient : public simplePSNet
{
private:
char _topic[MAX_NR_TOPICS_CLIENT][MAX_LEN_TOPICS+1] = { { 0 } };
char _data[MAX_NR_TOPICS_CLIENT][MAX_LEN_DATA+1] = { { 0 } };
bool saveData(char*, int);
bool getMessageFilter(char);
bool handleData();
int getTopicNr(char*);
int getFreeTopicNr();
public:
simplePSNetClient();
~simplePSNetClient();
bool publish(char*, char*);
bool publish(char*, int, char*, int);
bool subscribe(char*);
bool subscribe(char*, int);
bool unsubscribe(char*);
bool unsubscribe(char*, int);
};
class simplePSNetServer: public simplePSNet
{
private:
char _topic[MAX_NR_TOPICS_SERVER][MAX_LEN_TOPICS+1] = { { 0 } };
char _data[MAX_NR_TOPICS_SERVER][MAX_LEN_DATA+1] = { { 0 } };
bool saveData(char*, int);
bool getMessageFilter(char);
void writeDataToTopic(int, char*, char*);
bool handleData();
int getTopicNr(char*);
int getFreeTopicNr();
public:
simplePSNetServer();
~simplePSNetServer();
bool update(char*, int, char*, int);
};
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment