diff --git a/src/Device.cpp b/src/Device.cpp new file mode 100644 index 0000000..6012e6b --- /dev/null +++ b/src/Device.cpp @@ -0,0 +1,32 @@ +#include "SBDevice.h" + +SBMasterStorage SBMasterStorage::initialize() { + SBMasterStorage storage; +#if defined(ESP8266) + EEPROM.begin(SB_NETWORK_FLASH_SIZE); +#endif + EEPROM.get(0 + sizeof(SBNetworkDevice), storage); + if (storage.ID[0] != 'M' || storage.ID[1] != 'S') { + // We have to create a new one + storage.ID[0] = 'M'; + storage.ID[1] = 'S'; + Serial.println("Creating new Master Storage"); + EEPROM.put(0 + sizeof(SBNetworkDevice), storage); +#if defined(ESP8266) + EEPROM.commit(); + EEPROM.end(); +#endif + } + return storage; +} + +void SBMasterStorage::save() { +#if defined(ESP8266) + EEPROM.begin(SB_NETWORK_FLASH_SIZE); +#endif + EEPROM.put(sizeof(SBNetworkDevice), *this); +#if defined(ESP8266) + EEPROM.commit(); + EEPROM.end(); +#endif +} \ No newline at end of file diff --git a/src/SBDevice.h b/src/SBDevice.h index e67e1a9..05218fd 100644 --- a/src/SBDevice.h +++ b/src/SBDevice.h @@ -18,36 +18,11 @@ public: char ID[2] = { 'M', 'S' }; // MS stands for master storage SBMacAddress Slaves[MAX_CLIENTS]; - static SBMasterStorage initialize(){ - SBMasterStorage storage; -#if defined(ESP8266) - EEPROM.begin(FLASH_SIZE); -#endif - EEPROM.get(0 + sizeof(SBNetworkDevice), storage); - if (storage.ID[0] != 'M' || storage.ID[1] != 'S'){ - // We have to create a new one - storage.ID[0] = 'M'; - storage.ID[1] = 'S'; - Serial.println("Creating new Master Storage"); - EEPROM.put(0 + sizeof(SBNetworkDevice), storage); -#if defined(ESP8266) - EEPROM.commit(); - EEPROM.end(); -#endif - } - return storage; - } + static SBMasterStorage initialize(); - void save(){ -#if defined(ESP8266) - EEPROM.begin(FLASH_SIZE); -#endif - EEPROM.put(0 + sizeof(SBNetworkDevice), *this); -#if defined(ESP8266) - EEPROM.commit(); - EEPROM.end(); -#endif - } + void save(); }; +#define SB_NETWORK_FLASH_SIZE (sizeof(SBNetworkDevice) + sizeof(SBMasterStorage)) + #endif \ No newline at end of file diff --git a/src/SBNetwork.cpp b/src/SBNetwork.cpp index 0157e63..4281ad6 100644 --- a/src/SBNetwork.cpp +++ b/src/SBNetwork.cpp @@ -62,7 +62,7 @@ void SBNetwork::initialize(SBMacAddress mac){ this->radio.enableDynamicPayloads(); //this->radio.enableDynamicAck(); - this->radio.setAutoAck(true); + this->radio.setAutoAck(false); // We use our own ack handling //this->radio.enableAckPayload(); this->radio.setRetries(40, 5); @@ -89,7 +89,7 @@ void SBNetwork::initialize(SBMacAddress mac){ void SBNetwork::initializeNetworkDevice(SBNetworkDevice &device, SBMacAddress mac){ Serial.print(F("Try to read device config from internal flash...")); #if defined(ESP8266) - EEPROM.begin(FLASH_SIZE); + EEPROM.begin(SB_NETWORK_FLASH_SIZE); #endif EEPROM.get(0, device); // The first two bytes of a storage must always be 'D' 'S' ID to identifiy, that the device was already initiated if (device.ID[0] == 'D' && device.ID[1] == 'S'){ @@ -121,9 +121,9 @@ void SBNetwork::initializeNetworkDevice(SBNetworkDevice &device, SBMacAddress ma void SBNetwork::resetData(){ Serial.print(F("Erasing device configuration data...")); #if defined(ESP8266) - EEPROM.begin(FLASH_SIZE); + EEPROM.begin(SB_NETWORK_FLASH_SIZE); #endif - for(uint16_t i = 0; i < FLASH_SIZE; i++){ + for(uint16_t i = 0; i < SB_NETWORK_FLASH_SIZE; i++){ EEPROM.write(i, 0); } #if defined(ESP8266) @@ -147,7 +147,6 @@ bool SBNetwork::sendToDevice(SBMacAddress mac, void* message, uint8_t messageSiz frame.Header = header; uint8_t maxPackageSize = MAX_PACKAGE_SIZE; if (messageSize <= maxPackageSize){ - //Serial.print(" with no fragmentation"); // We can send directly without fragmentation frame.Header.FragmentNr = 0; frame.Header.FragmentCount = 1; @@ -166,15 +165,11 @@ bool SBNetwork::sendToDevice(SBMacAddress mac, void* message, uint8_t messageSiz return bSuccess; } else{ - //Serial.print(" with fragmentation "); // We have to send it in fragments uint8_t fragmentCount = messageSize / maxPackageSize; if ((fragmentCount * maxPackageSize) < messageSize){ fragmentCount++; } - //Serial.println(F("Have to send fragments")); - //Serial.print(F("Fragment count = ")); - //Serial.println(fragmentCount, DEC); for (uint8_t i = 0; i < fragmentCount; i++){ #if defined(_DEBUG) Serial.print("."); @@ -196,7 +191,7 @@ 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(" Failed "); #endif return false; } @@ -208,23 +203,74 @@ bool SBNetwork::sendToDevice(SBMacAddress mac, void* message, uint8_t messageSiz } } -bool SBNetwork::sendToDevice(SBNetworkFrame frame){ +bool SBNetwork::sendToDeviceInternal(SBNetworkFrame frame, bool waitForAck) { uint8_t bufferSize = sizeof(SBNetworkHeader) + frame.MessageSize; uint8_t buffer[32]; // = (uint8_t*)malloc(bufferSize); memcpy(buffer, &frame.Header, sizeof(SBNetworkHeader)); - if (frame.MessageSize > 0){ + if (frame.MessageSize > 0) { memcpy(buffer + sizeof(SBNetworkHeader), frame.Message, frame.MessageSize); } - // Send to broadcast - radio.stopListening(); - radio.openWritingPipe(frame.Header.ToAddress); - bool bSuccess = radio.write(buffer, bufferSize); - //free(buffer); - radio.openReadingPipe(0, this->NetworkDevice.MAC); - radio.startListening(); + 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++; + } 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); +} + bool SBNetwork::receiveInternal(SBNetworkFrame *frame) { uint8_t pipe = -1; if (radio.available(&pipe)) { @@ -278,20 +324,17 @@ bool SBNetwork::receiveMessage(void **message, uint8_t *messageSize, SBMacAddres return true; } else if (frame.Header.FragmentNr == 0) { + //Serial.print(frame.Header.FragmentNr + 1); Serial.print("/"); Serial.println(frame.Header.FragmentCount); // We have to receive more packages - //uint8_t *buffer = (uint8_t*)malloc((frame.MessageSize * frame.Header.FragmentCount)); memcpy(_ReadBuffer, frame.Message, maxPackageSize); - //free(frame.Message); - delay(10); + 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) { - //free(buffer); return false; } else { memcpy(_ReadBuffer + (frame.Header.FragmentNr * maxPackageSize), frame.Message, frame.MessageSize); - //free(frame.Message); if (frame.Header.FragmentNr == (frame.Header.FragmentCount - 1)) { // Last fragment received *message = _ReadBuffer; @@ -302,14 +345,9 @@ bool SBNetwork::receiveMessage(void **message, uint8_t *messageSize, SBMacAddres delay(10); } } - - //free(buffer); return false; } else { - if (frame.Message != NULL) { - //free(frame.Message); - } return false; } } @@ -339,7 +377,7 @@ bool SBNetwork::connectToNetwork(){ frame.Header = header; frame.Message = NULL; frame.MessageSize = 0; - bool bMasterAck = this->sendToDevice(frame); + bool bMasterAck = this->sendToDeviceInternal(frame, false); unsigned long started_waiting_at = millis(); boolean timeout = false; while (!this->receive(&frame)) { @@ -375,7 +413,7 @@ bool SBNetwork::connectToNetwork(){ conFrame.Header.PackageId = millis(); conFrame.Header.ToAddress = frame.Header.FromAddress; conFrame.MessageSize = 0; - if (!this->sendToDevice(conFrame)) { + if (!this->sendToDeviceInternal(conFrame, false)) { Serial.println(F("Failed - Sending pairing request")); } else { @@ -415,7 +453,7 @@ bool SBNetwork::connectToNetwork(){ } } -bool SBNetwork::pingDeviceInternal(SBMacAddress mac, bool waitForAck) { +bool SBNetwork::pingDevice(SBMacAddress mac){ SBNetworkHeader header; header.ToAddress = mac; header.FromAddress = this->NetworkDevice.MAC; @@ -431,35 +469,14 @@ bool SBNetwork::pingDeviceInternal(SBMacAddress mac, bool waitForAck) { bool bSend = this->sendToDevice(frame); if (bSend) { - if (waitForAck) { - long lNow = millis(); - SBNetworkFrame pingAckFrame; - while ((lNow + 100) > millis()) { - if (this->receiveInternal(&pingAckFrame)) { - if (pingAckFrame.Header.CommandType == SB_COMMAND_PING) { - Serial.println(F("Done - Device available")); - return true; - } - } - } -#if defined(_DEBUG) - Serial.println(F("Failed - Device not responding")); -#endif - return false; - } + Serial.println(F("Done - Device available")); } -#if defined(_DEBUG) else { Serial.println("Failed - Device not responding"); } -#endif return bSend; } -bool SBNetwork::pingDevice(SBMacAddress mac){ - return pingDeviceInternal(mac, true); -} - bool SBNetwork::handleCommandPackage(SBNetworkFrame *frame){ if (!this->RunAsClient) { // First check, if the device is listed in the storage @@ -472,81 +489,74 @@ bool SBNetwork::handleCommandPackage(SBNetworkFrame *frame){ } } - if (!bFound) { - // If an unknown device was detected, then never handle the network control traffic and never handle the messages -#ifdef _DEBUG - Serial.print(F("Unknown device detected with MAC: ")); - printAddress(frame->Header.FromAddress); - Serial.println(); -#endif - //return false; - } + // Look, if we must handle a command package switch (frame->Header.CommandType) { case SB_COMMAND_PING: { #ifdef _DEBUG Serial.println(F("Received 'PING'")); #endif + // Only, when the device is a paired slave, send a ping back if (bFound) { - pingDeviceInternal(frame->Header.FromAddress, false); + sendAckTo(frame->Header.FromAddress); } break; } case SB_COMMAND_SEARCH_MASTER: { -#ifdef _DEBUG - Serial.print(F("Received 'SEARCH_MASTER' Package. ")); -#endif + Serial.print(F("Received 'SEARCH_MASTER'. ")); + // When automatic Client adding is activated if (_EnableAutomaticClientAdding) { -#ifdef _DEBUG - Serial.println(F("Send MasterACK...")); -#endif + Serial.print(F("Send MasterACK...")); delay(20); bool bSend = sendMasterAck(frame->Header.FromAddress); if (bSend) { - return false; + Serial.println(F("Done")); + } + else { + Serial.println(F("Failed")); } - Serial.println(F("Done")); } -#if defined(_DEBUG) else { Serial.println(F("AutomaticClientAdding is deactivaed. Ignoring package.")); } -#endif break; } case SB_COMMAND_REQUEST_PAIRING: { -#ifdef _DEBUG - Serial.print(F("Received 'PAIRING_REQUEST' Package. ")); -#endif + Serial.print(F("Received 'PAIRING_REQUEST'. ")); + // When automatic Client adding is activated if (_EnableAutomaticClientAdding) { -#ifdef _DEBUG - Serial.println(F("Send MasterACK...")); -#endif + Serial.print(F("Send PairingACK... ")); delay(20); - // This is the point where we could stop orpcessing and wait for an user input on the controller to let the new device access the network + // 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 if (bSend) { + Serial.println(F("Done")); + Serial.print(F("Storing new MAC to MasterStorage... ")); addMac(frame->Header.FromAddress); + Serial.println(F("Done")); + } + else { + Serial.println(F("Failed")); } } -#if defined(_DEBUG) else { Serial.println(F("AutomaticClientAdding is deactivaed. Ignoring package.")); } -#endif break; } case SB_COMMAND_NO_COMMAND: - default: { - //Serial.println("No Command received. Passing through transport layer."); - return bFound; - break; - } +#ifdef _DEBUG + Serial.println(F("Received 'NO_COMMAND'")); +#endif + if (bFound) { + return sendAckTo(frame->Header.FromAddress); + } } // Package was handled by handleCommandPackage(); return false; } else { - return true; + return sendAckTo(frame->Header.FromAddress); } } @@ -563,7 +573,7 @@ bool SBNetwork::sendMasterAck(SBMacAddress mac){ frame.Header = header; frame.Message = (uint8_t*)&(this->NetworkDevice.NetworkKey); frame.MessageSize = sizeof(uint32_t); - return this->sendToDevice(frame); + return this->sendToDeviceInternal(frame, false); } else { return false; @@ -584,7 +594,7 @@ bool SBNetwork::sendPairingAck(SBMacAddress mac){ frame.Header = header; frame.Message = NULL; frame.MessageSize = 0; - return this->sendToDevice(frame); + return this->sendToDeviceInternal(frame, false); } else { return false; diff --git a/src/SBNetwork.h b/src/SBNetwork.h index ec16068..a14d3fe 100644 --- a/src/SBNetwork.h +++ b/src/SBNetwork.h @@ -65,6 +65,8 @@ class SBNetwork{ void initializeNetworkDevice(SBNetworkDevice &device, SBMacAddress mac); + bool sendToDeviceInternal(SBNetworkFrame frame, bool waitForAck); + bool sendToDevice(SBNetworkFrame frame); // Return false, if the package was handled internally and if it is not relevant for the end user @@ -80,7 +82,9 @@ class SBNetwork{ bool receiveMessage(void **message, uint8_t *messageSize, SBMacAddress *mac); - bool pingDeviceInternal(SBMacAddress mac, bool waitForAck); + bool waitForAckFrom(SBMacAddress mac); + + bool sendAckTo(SBMacAddress mac); public: /* @@ -183,5 +187,13 @@ public: return _EnableAutomaticClientAdding; } + /* + Returns the count of bytes that are reserved for SBNetworkLib in the internal flash. + If you want to use the internal flash, get shure not writing into the storage of SBNetwork. + */ + uint16_t getFlashOffset() { + return SB_NETWORK_FLASH_SIZE; + } + }; #endif diff --git a/src/SBNetwork_config.h b/src/SBNetwork_config.h index d0ea475..6337550 100644 --- a/src/SBNetwork_config.h +++ b/src/SBNetwork_config.h @@ -2,19 +2,23 @@ #ifndef _SB_NETWORK_CONFIG_ #define _SB_NETWORK_CONFIG_ -// Uncomment the following line, to compile the library for a master device. -//#define RUN_AS_MASTER - +// Generates details debug messages about sending and receiving data packages //#define _DEBUG -#define MASTER_CHECK_INTERVAL 0 // All slaves will ping the master every xxx milliseconds. if set to 0, they will not ping the master +// All slaves will ping the master every xxx milliseconds. if set to 0, they will not ping the master +#define MASTER_CHECK_INTERVAL 0 #define MAX_CLIENTS 10 -#define CLIENT_TIMEOUT 20000 +#define CLIENT_TIMEOUT 60000 -#define FLASH_SIZE 512 +// Waittime for an ACK package +#define ACK_WAIT 50 -#define ACK_WAIT 100 +// Count of trys to send a data package +#define RETRY_COUNT 10 + +// Milliseconds to wait between two retries +#define RETRY_DALY 40 #endif diff --git a/src/SBTypes.h b/src/SBTypes.h index cf86706..e83d2c5 100644 --- a/src/SBTypes.h +++ b/src/SBTypes.h @@ -15,6 +15,8 @@ #define SB_COMMAND_REQUEST_PAIRING 4 // Will be sent from the master after successfule adding a new client #define SB_COMMAND_PAIRING_ACK 5 +// Will always be sent, when packages are received and the other device is a known device +#define SB_COMMAND_ACK 6 class SBMacAddress{ public: