From 9b632383a8a3078683e210db3d57823a62fc73a8 Mon Sep 17 00:00:00 2001 From: Marcel Schulz Date: Sun, 11 Feb 2018 14:14:40 +0100 Subject: [PATCH] Removed self made ack handling. Now it seems to work very stable. --- src/SBDevice.cpp | 6 +- src/SBNetwork.cpp | 182 ++++++++++++++++++++--------------------- src/SBNetwork.h | 14 ++-- src/SBNetwork_config.h | 12 ++- 4 files changed, 106 insertions(+), 108 deletions(-) diff --git a/src/SBDevice.cpp b/src/SBDevice.cpp index 6012e6b..603d8f6 100644 --- a/src/SBDevice.cpp +++ b/src/SBDevice.cpp @@ -14,9 +14,11 @@ SBMasterStorage SBMasterStorage::initialize() { EEPROM.put(0 + sizeof(SBNetworkDevice), storage); #if defined(ESP8266) EEPROM.commit(); - EEPROM.end(); #endif - } + } +#if defined(ESP8266) + EEPROM.end(); +#endif return storage; } diff --git a/src/SBNetwork.cpp b/src/SBNetwork.cpp index 4281ad6..69e57a4 100644 --- a/src/SBNetwork.cpp +++ b/src/SBNetwork.cpp @@ -47,7 +47,7 @@ void SBNetwork::initialize(SBMacAddress mac){ if (!this->RunAsClient) { this->MasterStorage = SBMasterStorage::initialize(); for (uint8_t i = 0; i < MAX_CLIENTS; i++) { - Serial.print("Masterstorage Slot "); Serial.print(i); Serial.print(" "); + Serial.print(F("Masterstorage Slot ")); Serial.print(i); Serial.print(" "); printAddress(MasterStorage.Slaves[i]); Serial.println(); } @@ -62,9 +62,9 @@ void SBNetwork::initialize(SBMacAddress mac){ this->radio.enableDynamicPayloads(); //this->radio.enableDynamicAck(); - this->radio.setAutoAck(false); // We use our own ack handling + this->radio.setAutoAck(true); // We use the integrated package handling //this->radio.enableAckPayload(); - this->radio.setRetries(40, 5); + this->radio.setRetries(0, 15); // Listen at the own address this->radio.openReadingPipe(0, NetworkDevice.MAC); @@ -109,7 +109,7 @@ void SBNetwork::initializeNetworkDevice(SBNetworkDevice &device, SBMacAddress ma #if defined(ESP8266) EEPROM.commit(); #endif - Serial.println("Done"); + Serial.println(F("Done")); printDeviceData(device); } #if defined(ESP8266) @@ -136,7 +136,7 @@ void SBNetwork::resetData(){ bool SBNetwork::sendToDevice(SBMacAddress mac, void* message, uint8_t messageSize){ #if defined(_DEBUG) - Serial.print("Sending transmission"); + Serial.println(F("Sending transmission")); #endif SBNetworkHeader header; header.ToAddress = mac; @@ -156,10 +156,10 @@ bool SBNetwork::sendToDevice(SBMacAddress mac, void* message, uint8_t messageSiz bool bSuccess = this->sendToDevice(frame); #if defined(_DEBUG) if (bSuccess) { - Serial.println(" Done"); + Serial.println(F(" Done")); } else { - Serial.println(" Failed"); + Serial.println(F(" Failed")); } #endif return bSuccess; @@ -171,6 +171,7 @@ bool SBNetwork::sendToDevice(SBMacAddress mac, void* message, uint8_t messageSiz fragmentCount++; } for (uint8_t i = 0; i < fragmentCount; i++){ + delay(FRAGMENT_DELAY); #if defined(_DEBUG) Serial.print("."); #endif @@ -191,19 +192,19 @@ bool SBNetwork::sendToDevice(SBMacAddress mac, void* message, uint8_t messageSiz bool bSuccess = this->sendToDevice(frame); if (!bSuccess){ #if defined(_DEBUG) - Serial.println(" Failed "); + Serial.println(F(" Failed ")); #endif return false; } } #if defined(_DEBUG) - Serial.println(" Done"); + Serial.println(F(" Done")); #endif return true; } } -bool SBNetwork::sendToDeviceInternal(SBNetworkFrame frame, bool waitForAck) { +bool SBNetwork::sendToDeviceInternal(SBNetworkFrame frame) { uint8_t bufferSize = sizeof(SBNetworkHeader) + frame.MessageSize; uint8_t buffer[32]; // = (uint8_t*)malloc(bufferSize); memcpy(buffer, &frame.Header, sizeof(SBNetworkHeader)); @@ -211,64 +212,21 @@ bool SBNetwork::sendToDeviceInternal(SBNetworkFrame frame, bool waitForAck) { memcpy(buffer + sizeof(SBNetworkHeader), frame.Message, frame.MessageSize); } bool bSuccess = false; - uint8_t iCounter = 0; - while (!bSuccess && iCounter < RETRY_COUNT) { - // Send to broadcast - radio.stopListening(); - radio.openWritingPipe(frame.Header.ToAddress); - bSuccess = radio.write(buffer, bufferSize); - radio.openReadingPipe(0, this->NetworkDevice.MAC); - radio.startListening(); - if (bSuccess) { - bSuccess = waitForAck ? waitForAckFrom(frame.Header.ToAddress) : true; - } - delay(40); // Waittime between two sendings - iCounter++; - } + radio.stopListening(); + radio.openWritingPipe(frame.Header.ToAddress); + +#if defined(_DEBUG) + Serial.print(millis()); + Serial.println(F(" Sending physical data")); +#endif + bSuccess = radio.write(buffer, bufferSize); + radio.openReadingPipe(0, this->NetworkDevice.MAC); + radio.startListening(); return bSuccess; } bool SBNetwork::sendToDevice(SBNetworkFrame frame){ - return sendToDeviceInternal(frame, true); -} - -bool SBNetwork::waitForAckFrom(SBMacAddress mac) { -#if defined(_DEBUG) - Serial.print(F("Wait for Ack... ")); -#endif - long lNow = millis(); - // We need the counter in case of the unoccationally case, that during the wait, the timer overflows ans starts with 0 - uint16_t iCounter = 1; - SBNetworkFrame frame; - while (lNow + ACK_WAIT > millis() && iCounter) { - if (this->receiveInternal(&frame)) { - if (frame.Header.FromAddress.isEquals(mac)) { - if (frame.Header.CommandType == SB_COMMAND_ACK) { -#if defined(_DEBUG) - Serial.print(F("Done - Counter = ")); Serial.println(iCounter); -#endif - return true; - } - } - } - iCounter++; - } -#if defined(_DEBUG) - Serial.print(F("Failed - Counter = ")); Serial.println(iCounter); -#endif - return false; -} - -bool SBNetwork::sendAckTo(SBMacAddress mac) { - SBNetworkFrame frame; - frame.Header.ToAddress = mac; - frame.Header.FromAddress = this->NetworkDevice.MAC; - frame.Header.FragmentCount = 1; - frame.Header.FragmentNr = 0; - frame.Header.PackageId = millis(); - frame.Header.CommandType = SB_COMMAND_ACK; - frame.MessageSize = 0; - return sendToDeviceInternal(frame, false); + return sendToDeviceInternal(frame); } bool SBNetwork::receiveInternal(SBNetworkFrame *frame) { @@ -301,50 +259,71 @@ bool SBNetwork::receive(SBNetworkFrame *frame){ // We must check, if the received package is a NO_COMMAND_PACKAGE otherwise we have to handle it internally return this->handleCommandPackage(frame); } + return false; } bool SBNetwork::receiveMessage(void **message, uint8_t *messageSize, SBMacAddress *mac){ uint8_t pipe = -1; uint8_t maxPackageSize = MAX_PACKAGE_SIZE; if (radio.available()){ +#if defined(_DEBUG) + Serial.print(millis()); + Serial.println(F(" Radio available")); +#endif SBNetworkFrame frame; bool bReceive = this->receive(&frame); if (bReceive) { #ifdef _DEBUG - Serial.print("Incomming transmission from "); + Serial.print(F("Incomming transmission from ")); printAddress(frame.Header.FromAddress); Serial.println(); #endif if (frame.Header.FragmentCount == 1) { +#ifdef _DEBUG + Serial.println(F("no fragments")); +#endif // We only have to receive this package memcpy(_ReadBuffer, frame.Message, maxPackageSize); (*message) = _ReadBuffer; (*messageSize) = frame.MessageSize; (*mac) = frame.Header.FromAddress; + return true; } else if (frame.Header.FragmentNr == 0) { - //Serial.print(frame.Header.FragmentNr + 1); Serial.print("/"); Serial.println(frame.Header.FragmentCount); +#ifdef _DEBUG + Serial.println(F("with fragments")); +#endif + Serial.print(millis()); Serial.print(F(" Fragment received ")); Serial.print(frame.Header.FragmentNr + 1); Serial.print("/"); Serial.println(frame.Header.FragmentCount); // We have to receive more packages memcpy(_ReadBuffer, frame.Message, maxPackageSize); - delay(50); // We need a delay here, because the opposite needs time to send the next package - while (radio.available()) { - bReceive = this->receive(&frame); - if (!bReceive) { - return false; - } - else { + //delay(50); // We need a delay here, because the opposite needs time to send the next package + unsigned long timeout = millis() + FRAGMENT_TIMEOUT; + _AwaitingFragmentPackage = true; + while (radio.available() || timeout > millis()) { + if (this->receive(&frame)){ + Serial.print(millis()); Serial.print(F(" Fragment received ")); Serial.print(frame.Header.FragmentNr + 1); + Serial.print(F("/")); Serial.println(frame.Header.FragmentCount); memcpy(_ReadBuffer + (frame.Header.FragmentNr * maxPackageSize), frame.Message, frame.MessageSize); + // Now wait again for the next fragment + timeout = millis() + FRAGMENT_TIMEOUT; if (frame.Header.FragmentNr == (frame.Header.FragmentCount - 1)) { // Last fragment received *message = _ReadBuffer; *messageSize = ((frame.Header.FragmentCount - 1) * maxPackageSize) + frame.MessageSize; (*mac) = frame.Header.FromAddress; + _AwaitingFragmentPackage = false; return true; } - delay(10); + //delay(10); } + delay(1); } + _AwaitingFragmentPackage = false; + + Serial.print(millis()); + Serial.println(F(" Fragment timeout")); + return false; } else { @@ -377,7 +356,8 @@ bool SBNetwork::connectToNetwork(){ frame.Header = header; frame.Message = NULL; frame.MessageSize = 0; - bool bMasterAck = this->sendToDeviceInternal(frame, false); + bool bMasterAck = this->sendToDeviceInternal(frame); + unsigned long started_waiting_at = millis(); boolean timeout = false; while (!this->receive(&frame)) { @@ -394,9 +374,10 @@ bool SBNetwork::connectToNetwork(){ else { if (frame.Header.CommandType != SB_COMMAND_MASTER_ACK) { if (frame.MessageSize > 0) { - free(frame.Message); + //free(frame.Message); } Serial.println(F("Failed - Got answer but no master ack")); + Serial.println(frame.Header.CommandType); return false; } else { @@ -413,7 +394,7 @@ bool SBNetwork::connectToNetwork(){ conFrame.Header.PackageId = millis(); conFrame.Header.ToAddress = frame.Header.FromAddress; conFrame.MessageSize = 0; - if (!this->sendToDeviceInternal(conFrame, false)) { + if (!this->sendToDeviceInternal(conFrame)) { Serial.println(F("Failed - Sending pairing request")); } else { @@ -429,6 +410,7 @@ bool SBNetwork::connectToNetwork(){ } if (frame.Header.CommandType != SB_COMMAND_PAIRING_ACK) { Serial.println(F("Failed - Pairing rejected from the master")); + Serial.println(frame.Header.CommandType); return false; } else { @@ -436,8 +418,8 @@ bool SBNetwork::connectToNetwork(){ this->NetworkDevice.NetworkKey = *(frame.Message); this->NetworkDevice.ConnectedToMaster = -1; EEPROM.put(0, NetworkDevice); - Serial.println("Suceeded"); - Serial.print("Try to ping to master..."); + Serial.println(F("Suceeded")); + Serial.print(F("Try to ping to master...")); delay(100); } } @@ -472,7 +454,7 @@ bool SBNetwork::pingDevice(SBMacAddress mac){ Serial.println(F("Done - Device available")); } else { - Serial.println("Failed - Device not responding"); + Serial.println(F("Failed - Device not responding")); } return bSend; } @@ -495,10 +477,6 @@ bool SBNetwork::handleCommandPackage(SBNetworkFrame *frame){ #ifdef _DEBUG Serial.println(F("Received 'PING'")); #endif - // Only, when the device is a paired slave, send a ping back - if (bFound) { - sendAckTo(frame->Header.FromAddress); - } break; } case SB_COMMAND_SEARCH_MASTER: { @@ -506,7 +484,7 @@ bool SBNetwork::handleCommandPackage(SBNetworkFrame *frame){ // When automatic Client adding is activated if (_EnableAutomaticClientAdding) { Serial.print(F("Send MasterACK...")); - delay(20); + delay(100); bool bSend = sendMasterAck(frame->Header.FromAddress); if (bSend) { Serial.println(F("Done")); @@ -525,7 +503,7 @@ bool SBNetwork::handleCommandPackage(SBNetworkFrame *frame){ // When automatic Client adding is activated if (_EnableAutomaticClientAdding) { Serial.print(F("Send PairingACK... ")); - delay(20); + delay(100); // This is the point where we could stop prpcessing and wait for an user input on the controller to let the new device access the network bool bSend = sendPairingAck(frame->Header.FromAddress); // If sending was successfull, then add the new slave @@ -544,19 +522,37 @@ bool SBNetwork::handleCommandPackage(SBNetworkFrame *frame){ } break; } - case SB_COMMAND_NO_COMMAND: + case SB_COMMAND_NO_COMMAND: { #ifdef _DEBUG Serial.println(F("Received 'NO_COMMAND'")); #endif if (bFound) { - return sendAckTo(frame->Header.FromAddress); + if ((_AwaitingFragmentPackage && frame->Header.FragmentNr > 0) || (!_AwaitingFragmentPackage && frame->Header.FragmentNr == 0)) { + return true; + } } + break; + } } // Package was handled by handleCommandPackage(); return false; } else { - return sendAckTo(frame->Header.FromAddress); + // Look, if we must handle a command package for a client + switch (frame->Header.CommandType) { + case SB_COMMAND_NO_COMMAND: { +#ifdef _DEBUG + Serial.println(F("Received 'NO_COMMAND'")); +#endif + if ((_AwaitingFragmentPackage && frame->Header.FragmentNr > 0) || (!_AwaitingFragmentPackage && frame->Header.FragmentNr == 0)) { + return true; + } + } + case SB_COMMAND_MASTER_ACK: + case SB_COMMAND_PAIRING_ACK: + return true; + } + return false; } } @@ -573,7 +569,7 @@ bool SBNetwork::sendMasterAck(SBMacAddress mac){ frame.Header = header; frame.Message = (uint8_t*)&(this->NetworkDevice.NetworkKey); frame.MessageSize = sizeof(uint32_t); - return this->sendToDeviceInternal(frame, false); + return this->sendToDeviceInternal(frame); } else { return false; @@ -594,7 +590,7 @@ bool SBNetwork::sendPairingAck(SBMacAddress mac){ frame.Header = header; frame.Message = NULL; frame.MessageSize = 0; - return this->sendToDeviceInternal(frame, false); + return this->sendToDeviceInternal(frame); } else { return false; @@ -605,13 +601,13 @@ bool SBNetwork::checkMaster(){ if (this->RunAsClient) { if (this->pingDevice(this->NetworkDevice.MasterMAC)) { #ifdef _DEBUG - Serial.println("Master OK"); + Serial.println(F("Master OK")); #endif return true; } else { #ifdef _DEBUG - Serial.println("Master ERROR"); + Serial.println(F("Master ERROR")); #endif return false; } diff --git a/src/SBNetwork.h b/src/SBNetwork.h index efb407e..e87b3ef 100644 --- a/src/SBNetwork.h +++ b/src/SBNetwork.h @@ -2,7 +2,7 @@ #ifndef _SB_NETWORK_ #define _SB_NETWORK_ -#define SB_VERSION "1.0.4" +#define SB_VERSION "1.0.5" #include #include @@ -13,6 +13,8 @@ #define BROADCAST_MAC (SBMacAddress(0x9E, 0x0E, 0x9E, 0x0E, 0x9E)) #define EMPTY_MAC (SBMacAddress(0x00, 0x00, 0x00, 0x00, 0x00)) +void printAddress(byte address[5]); + class SBNetwork{ private: /* @@ -56,6 +58,10 @@ class SBNetwork{ */ SBMacAddress _LastReceivedFromAddress; /** + / Stores the flag, that tells the handle command function to await a fragent or not + */ + bool _AwaitingFragmentPackage = false; + /** Enables or disables automatical client adding, when receiving a pairing resuest. This is false by default. */ @@ -63,7 +69,7 @@ class SBNetwork{ void initializeNetworkDevice(SBNetworkDevice &device, SBMacAddress mac); - bool sendToDeviceInternal(SBNetworkFrame frame, bool waitForAck); + bool sendToDeviceInternal(SBNetworkFrame frame); bool sendToDevice(SBNetworkFrame frame); @@ -80,10 +86,6 @@ class SBNetwork{ bool receiveMessage(void **message, uint8_t *messageSize, SBMacAddress *mac); - bool waitForAckFrom(SBMacAddress mac); - - bool sendAckTo(SBMacAddress mac); - public: /* * Define the standard addresses for the sensor network diff --git a/src/SBNetwork_config.h b/src/SBNetwork_config.h index 6337550..e6437cb 100644 --- a/src/SBNetwork_config.h +++ b/src/SBNetwork_config.h @@ -3,6 +3,7 @@ #define _SB_NETWORK_CONFIG_ // Generates details debug messages about sending and receiving data packages + //#define _DEBUG // All slaves will ping the master every xxx milliseconds. if set to 0, they will not ping the master @@ -12,13 +13,10 @@ #define CLIENT_TIMEOUT 60000 -// Waittime for an ACK package -#define ACK_WAIT 50 +// Milliseconds to wait for fragmented packages +#define FRAGMENT_TIMEOUT 80 -// Count of trys to send a data package -#define RETRY_COUNT 10 - -// Milliseconds to wait between two retries -#define RETRY_DALY 40 +// Milliseconds to wait between two fragment sendings +#define FRAGMENT_DELAY 10 #endif