From adcde6fb6cd2e4a8e13345dd0d88f3929a5398da Mon Sep 17 00:00:00 2001 From: jgromes Date: Sat, 28 Sep 2019 12:49:44 +0200 Subject: [PATCH] Added option to use only static allocations --- src/TypeDef.h | 5 + src/modules/ESP8266.cpp | 42 +++++-- src/modules/SX126x.cpp | 38 ++++-- src/modules/XBee.cpp | 77 +++++++++--- src/modules/XBee.h | 6 +- src/protocols/MQTT.cpp | 216 ++++++++++++++++++++------------ src/protocols/PhysicalLayer.cpp | 42 +++++-- src/protocols/RTTY.cpp | 26 ++-- src/protocols/RTTY.h | 6 +- 9 files changed, 319 insertions(+), 139 deletions(-) diff --git a/src/TypeDef.h b/src/TypeDef.h index e36218ef..2099187c 100644 --- a/src/TypeDef.h +++ b/src/TypeDef.h @@ -10,6 +10,11 @@ // the following platforms do not support SoftwareSerial library #define SOFTWARE_SERIAL_UNSUPPORTED (defined(ESP32) || defined(SAMD_SERIES) || defined (ARDUINO_ARCH_STM32)) +// uncomment to enable static-only memory management: no dynamic allocation will be performed +// Warning: Large static arrays will be created in some methods. It is also not advised to send large packets in this mode. +//#define STATIC_ONLY +#define STATIC_ARRAY_SIZE 256 + #define RADIOLIB_DEBUG_PORT Serial //#define RADIOLIB_DEBUG diff --git a/src/modules/ESP8266.cpp b/src/modules/ESP8266.cpp index 7f7e47b5..6160dc9b 100644 --- a/src/modules/ESP8266.cpp +++ b/src/modules/ESP8266.cpp @@ -52,8 +52,12 @@ int16_t ESP8266::join(const char* ssid, const char* password) { // build AT command const char* atStr = "AT+CWJAP_CUR=\""; - uint8_t cmdLen = strlen(atStr) + strlen(ssid) + strlen(password) + 4; - char* cmd = new char[cmdLen + 1]; + #ifdef STATIC_ONLY + char cmd[STATIC_ARRAY_SIZE]; + #else + uint8_t cmdLen = strlen(atStr) + strlen(ssid) + strlen(password) + 4; + char* cmd = new char[cmdLen + 1]; + #endif strcpy(cmd, atStr); strcat(cmd, ssid); strcat(cmd, "\",\""); @@ -62,7 +66,9 @@ int16_t ESP8266::join(const char* ssid, const char* password) { // send command bool res = _mod->ATsendCommand(cmd); - delete[] cmd; + #ifndef STATIC_ONLY + delete[] cmd; + #endif if(!res) { return(ERR_AT_FAILED); } @@ -87,7 +93,11 @@ int16_t ESP8266::openTransportConnection(const char* host, const char* protocol, if((strcmp(protocol, "TCP") == 0) && (tcpKeepAlive > 0)) { cmdLen += strlen(tcpKeepAliveStr) + 1; } - char* cmd = new char[cmdLen + 1]; + #ifdef STATIC_ONLY + char cmd[STATIC_ARRAY_SIZE]; + #else + char* cmd = new char[cmdLen + 1]; + #endif strcpy(cmd, atStr); strcat(cmd, protocol); strcat(cmd, "\",\""); @@ -101,7 +111,9 @@ int16_t ESP8266::openTransportConnection(const char* host, const char* protocol, // send command bool res = _mod->ATsendCommand(cmd); - delete[] cmd; + #ifndef STATIC_ONLY + delete[] cmd; + #endif if(!res) { return(ERR_AT_FAILED); } @@ -122,13 +134,19 @@ int16_t ESP8266::send(const char* data) { char lenStr[8]; itoa(strlen(data), lenStr, 10); const char* atStr = "AT+CIPSEND="; - char* cmd = new char[strlen(atStr) + strlen(lenStr) + 1]; + #ifdef STATIC_ONLY + char cmd[STATIC_ARRAY_SIZE]; + #else + char* cmd = new char[strlen(atStr) + strlen(lenStr) + 1]; + #endif strcpy(cmd, atStr); strcat(cmd, lenStr); // send command bool res = _mod->ATsendCommand(cmd); - delete[] cmd; + #ifndef STATIC_ONLY + delete[] cmd; + #endif if(!res) { return(ERR_AT_FAILED); } @@ -146,13 +164,19 @@ int16_t ESP8266::send(uint8_t* data, uint32_t len) { char lenStr[8]; itoa(len, lenStr, 10); const char atStr[] = "AT+CIPSEND="; - char* cmd = new char[strlen(atStr) + strlen(lenStr) + 1]; + #ifdef STATIC_ONLY + char cmd[STATIC_ARRAY_SIZE]; + #else + char* cmd = new char[strlen(atStr) + strlen(lenStr) + 1]; + #endif strcpy(cmd, atStr); strcat(cmd, lenStr); // send command bool res = _mod->ATsendCommand(cmd); - delete[] cmd; + #ifndef STATIC_ONLY + delete[] cmd; + #endif if(!res) { return(ERR_AT_FAILED); } diff --git a/src/modules/SX126x.cpp b/src/modules/SX126x.cpp index 74029d5f..16b04a1d 100644 --- a/src/modules/SX126x.cpp +++ b/src/modules/SX126x.cpp @@ -1030,12 +1030,18 @@ int16_t SX126x::setPaConfig(uint8_t paDutyCycle, uint8_t deviceSel, uint8_t hpMa } int16_t SX126x::writeRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) { - uint8_t* dat = new uint8_t[2 + numBytes]; + #ifdef STATIC_ONLY + uint8_t dat[STATIC_ARRAY_SIZE + 2]; + #else + uint8_t* dat = new uint8_t[2 + numBytes]; + #endif dat[0] = (uint8_t)((addr >> 8) & 0xFF); dat[1] = (uint8_t)(addr & 0xFF); memcpy(dat + 2, data, numBytes); int16_t state = SPIwriteCommand(SX126X_CMD_WRITE_REGISTER, dat, 2 + numBytes); - delete[] dat; + #ifndef STATIC_ONLY + delete[] dat; + #endif return(state); } @@ -1045,22 +1051,34 @@ int16_t SX126x::readRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) { } int16_t SX126x::writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset) { - uint8_t* dat = new uint8_t[1 + numBytes]; + #ifdef STATIC_ONLY + uint8_t dat[STATIC_ARRAY_SIZE + 1]; + #else + uint8_t* dat = new uint8_t[1 + numBytes]; + #endif dat[0] = offset; memcpy(dat + 1, data, numBytes); int16_t state = SPIwriteCommand(SX126X_CMD_WRITE_BUFFER, dat, 1 + numBytes); - delete[] dat; + #ifndef STATIC_ONLY + delete[] dat; + #endif return(state); } int16_t SX126x::readBuffer(uint8_t* data, uint8_t numBytes) { // offset will be always set to 0 (one extra NOP is sent) - uint8_t* dat = new uint8_t[1 + numBytes]; + #ifdef STATIC_ONLY + uint8_t dat[STATIC_ARRAY_SIZE + 1]; + #else + uint8_t* dat = new uint8_t[1 + numBytes]; + #endif dat[0] = SX126X_CMD_NOP; memcpy(dat + 1, data, numBytes); int16_t state = SPIreadCommand(SX126X_CMD_READ_BUFFER, dat, 1 + numBytes); memcpy(data, dat + 1, numBytes); - delete[] dat; + #ifndef STATIC_ONLY + delete[] dat; + #endif return(state); } @@ -1180,7 +1198,7 @@ int16_t SX126x::setFrequencyRaw(float freq) { int16_t SX126x::config(uint8_t modem) { // set regulator mode - uint8_t* data = new uint8_t[1]; + uint8_t data[7]; data[0] = SX126X_REGULATOR_DC_DC; int16_t state = SPIwriteCommand(SX126X_CMD_SET_REGULATOR_MODE, data, 1); if(state != ERR_NONE) { @@ -1208,8 +1226,6 @@ int16_t SX126x::config(uint8_t modem) { } // set CAD parameters - delete[] data; - data = new uint8_t[7]; data[0] = SX126X_CAD_ON_8_SYMB; data[1] = _sf + 13; data[2] = 10; @@ -1230,8 +1246,6 @@ int16_t SX126x::config(uint8_t modem) { } // calibrate all blocks - delete[] data; - data = new uint8_t[1]; data[0] = SX126X_CALIBRATE_ALL; state = SPIwriteCommand(SX126X_CMD_CALIBRATE, data, 1); if(state != ERR_NONE) { @@ -1242,8 +1256,6 @@ int16_t SX126x::config(uint8_t modem) { delayMicroseconds(1); while(digitalRead(_mod->getRx())); - delete[] data; - return(ERR_NONE); } diff --git a/src/modules/XBee.cpp b/src/modules/XBee.cpp index 9be17456..a2397d61 100644 --- a/src/modules/XBee.cpp +++ b/src/modules/XBee.cpp @@ -5,7 +5,6 @@ XBee::XBee(Module* mod) { _frameID = 0x01; _frameLength = 0; _frameHeaderProcessed = false; - _packetData = new char[0]; } int16_t XBee::begin(long speed) { @@ -69,7 +68,11 @@ int16_t XBee::transmit(uint8_t* dest, uint8_t* destNetwork, const char* payload, // build the frame size_t payloadLen = strlen(payload); size_t dataLen = 8 + 2 + 1 + 1 + payloadLen; - uint8_t* cmd = new uint8_t[dataLen]; + #ifdef STATIC_ONLY + uint8_t cmd[STATIC_ARRAY_SIZE]; + #else + uint8_t* cmd = new uint8_t[dataLen]; + #endif memcpy(cmd, dest, 8); memcpy(cmd + 8, destNetwork, 2); cmd[10] = radius; @@ -79,7 +82,9 @@ int16_t XBee::transmit(uint8_t* dest, uint8_t* destNetwork, const char* payload, // send frame uint8_t frameID = _frameID++; sendApiFrame(XBEE_API_FRAME_ZIGBEE_TRANSMIT_REQUEST, frameID, cmd, dataLen); - delete[] cmd; + #ifndef STATIC_ONLY + delete[] cmd; + #endif // get response code return(readApiFrame(frameID, 5)); @@ -114,20 +119,28 @@ size_t XBee::available() { return(0); } - uint8_t* frame = new uint8_t[_frameLength]; //24 + #ifdef STATIC_ONLY + char frame[STATIC_ARRAY_SIZE]; + #else + uint8_t* frame = new uint8_t[_frameLength]; + #endif for(size_t i = 0; i < _frameLength; i++) { frame[i] = _mod->ModuleSerial->read(); } // save packet source and data size_t payloadLength = _frameLength - 12; - delete[] _packetData; - _packetData = new char[payloadLength]; + #ifndef STATIC_ONLY + delete[] _packetData; + _packetData = new char[payloadLength]; + #endif memcpy(_packetData, frame + 12, payloadLength - 1); _packetData[payloadLength - 1] = '\0'; memcpy(_packetSource, frame + 1, 8); - delete[] frame; + #ifndef STATIC_ONLY + delete[] frame; + #endif _frameLength = 0; _frameHeaderProcessed = false; @@ -219,22 +232,34 @@ int16_t XBeeSerial::setDestinationAddress(const char* destinationAddressHigh, co // set higher address bytes RADIOLIB_DEBUG_PRINTLN(F("Setting address (high) ...")); - char* addressHigh = new char[strlen(destinationAddressHigh) + 4]; + #ifdef STATIC_ONLY + char addressHigh[13]; + #else + char* addressHigh = new char[strlen(destinationAddressHigh) + 4]; + #endif strcpy(addressHigh, "ATDH"); strcat(addressHigh, destinationAddressHigh); bool res = _mod->ATsendCommand(addressHigh); - delete[] addressHigh; + #ifndef STATIC_ONLY + delete[] addressHigh; + #endif if(!res) { return(ERR_AT_FAILED); } // set lower address bytes RADIOLIB_DEBUG_PRINTLN(F("Setting address (low) ...")); - char* addressLow = new char[strlen(destinationAddressLow) + 4]; + #ifdef STATIC_ONLY + char addressLow[13]; + #else + char* addressLow = new char[strlen(destinationAddressLow) + 4]; + #endif strcpy(addressLow, "ATDL"); strcat(addressLow, destinationAddressLow); res = _mod->ATsendCommand(addressLow); - delete[] addressLow; + #ifndef STATIC_ONLY + delete[] addressLow; + #endif if(!res) { return(ERR_AT_FAILED); } @@ -257,11 +282,17 @@ int16_t XBeeSerial::setPanId(const char* panId) { // set PAN ID RADIOLIB_DEBUG_PRINTLN(F("Setting PAN ID ...")); - char* cmd = new char[strlen(panId) + 4]; + #ifdef STATIC_ONLY + char cmd[21]; + #else + char* cmd = new char[strlen(panId) + 4]; + #endif strcpy(cmd, "ATID"); strcat(cmd, panId); bool res = _mod->ATsendCommand(cmd); - delete[] cmd; + #ifndef STATIC_ONLY + delete[] cmd; + #endif if(!res) { return(ERR_AT_FAILED); } @@ -333,7 +364,11 @@ void XBee::sendApiFrame(uint8_t type, uint8_t id, const char* data) { void XBee::sendApiFrame(uint8_t type, uint8_t id, uint8_t* data, uint16_t length) { // build the API frame size_t frameLength = 1 + 2 + length + 1 + 2; - uint8_t* frame = new uint8_t[frameLength]; + #ifdef STATIC_ONLY + uint8_t frame[STATIC_ARRAY_SIZE]; + #else + uint8_t* frame = new uint8_t[frameLength]; + #endif frame[0] = 0x7E; // start delimiter frame[1] = ((length + 2) & 0xFF00) >> 8; // length MSB @@ -355,7 +390,9 @@ void XBee::sendApiFrame(uint8_t type, uint8_t id, uint8_t* data, uint16_t length } // deallocate memory - delete[] frame; + #ifndef STATIC_ONLY + delete[] frame; + #endif } int16_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos, uint16_t timeout) { @@ -381,7 +418,11 @@ int16_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos, uint16_t timeout) { RADIOLIB_DEBUG_PRINTLN(numBytes); // read the response - uint8_t* resp = new uint8_t[numBytes]; + #ifdef STATIC_ONLY + uint8_t resp[STATIC_ARRAY_SIZE]; + #else + uint8_t* resp = new uint8_t[numBytes]; + #endif for(uint16_t i = 0; i < numBytes; i++) { resp[i] = _mod->ModuleSerial->read(); } @@ -410,7 +451,9 @@ int16_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos, uint16_t timeout) { // codePos does not include start delimiter and frame ID uint8_t code = resp[codePos]; - delete[] resp; + #ifndef STATIC_ONLY + delete[] resp; + #endif return(code); } diff --git a/src/modules/XBee.h b/src/modules/XBee.h index 470d7b7c..9091c9cc 100644 --- a/src/modules/XBee.h +++ b/src/modules/XBee.h @@ -176,7 +176,11 @@ class XBee { size_t _frameLength; bool _frameHeaderProcessed; - char* _packetData; + #ifdef STATIC_ONLY + char _packetData[STATIC_ARRAY_SIZE]; + #else + char* _packetData = new char[0]; + #endif uint8_t _packetSource[8]; int16_t confirmChanges(); diff --git a/src/protocols/MQTT.cpp b/src/protocols/MQTT.cpp index cf151caf..a5291326 100644 --- a/src/protocols/MQTT.cpp +++ b/src/protocols/MQTT.cpp @@ -18,21 +18,25 @@ int16_t MQTTClient::connect(const char* host, const char* clientId, const char* remainingLength += (2 + userNameLen); } if(passwordLen > 0) { - remainingLength += (2 + passwordLen); + remainingLength += (2 + passwordLen); } if((willTopicLen > 0) && (willMessageLen > 0)) { remainingLength += (2 + willTopicLen) + (2 + willMessageLen); } uint8_t encoded[] = {0, 0, 0, 0}; size_t encodedBytes = encodeLength(remainingLength, encoded); - + // build the CONNECT packet - uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength]; - + #ifdef STATIC_ONLY + uint8_t packet[256]; + #else + uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength]; + #endif + // fixed header packet[0] = (MQTT_CONNECT << 4) | 0b0000; memcpy(packet + 1, encoded, encodedBytes); - + // variable header // protocol name size_t pos = encodedBytes + 1; @@ -40,42 +44,42 @@ int16_t MQTTClient::connect(const char* host, const char* clientId, const char* packet[pos++] = 0x04; memcpy(packet + pos, "MQTT", 4); pos += 4; - + // protocol level - packet[pos++] = 0x04; - - // flags + packet[pos++] = 0x04; + + // flags packet[pos++] = 0x00; if(cleanSession) { packet[encodedBytes + 8] |= MQTT_CONNECT_CLEAN_SESSION; } - + // keep alive interval in seconds packet[pos++] = (keepAlive & 0xFF00) >> 8; packet[pos++] = keepAlive & 0x00FF; - + // payload // clientId packet[pos++] = (clientIdLen & 0xFF00) >> 8; packet[pos++] = clientIdLen & 0x00FF; memcpy(packet + pos, clientId, clientIdLen); pos += clientIdLen; - + // will topic and message if((willTopicLen > 0) && (willMessageLen > 0)) { packet[encodedBytes + 8] |= MQTT_CONNECT_WILL_FLAG; - + packet[pos++] = (willTopicLen & 0xFF00) >> 8; packet[pos++] = willTopicLen & 0x00FF; memcpy(packet + pos, willTopic, willTopicLen); pos += willTopicLen; - + packet[pos++] = (willMessageLen & 0xFF00) >> 8; packet[pos++] = willMessageLen & 0x00FF; memcpy(packet + pos, willMessage, willMessageLen); pos += willMessageLen; } - + // user name if(userNameLen > 0) { packet[encodedBytes + 8] |= MQTT_CONNECT_USER_NAME_FLAG; @@ -84,7 +88,7 @@ int16_t MQTTClient::connect(const char* host, const char* clientId, const char* memcpy(packet + pos, userName, userNameLen); pos += userNameLen; } - + // password if(passwordLen > 0) { packet[encodedBytes + 8] |= MQTT_CONNECT_PASSWORD_FLAG; @@ -93,54 +97,66 @@ int16_t MQTTClient::connect(const char* host, const char* clientId, const char* memcpy(packet + pos, password, passwordLen); pos += passwordLen; } - + // create TCP connection int16_t state = _tl->openTransportConnection(host, "TCP", _port, keepAlive); if(state != ERR_NONE) { - delete[] packet; + #ifndef STATIC_ONLY + delete[] packet; + #endif return(state); } - + // send MQTT packet state = _tl->send(packet, 1 + encodedBytes + remainingLength); - delete[] packet; + #ifndef STATIC_ONLY + delete[] packet; + #endif if(state != ERR_NONE) { return(state); } - + // get the response length (MQTT CONNACK response has to be 4 bytes long) size_t numBytes = _tl->getNumBytes(); if(numBytes != 4) { return(ERR_RESPONSE_MALFORMED_AT); } - + // read the response - uint8_t* response = new uint8_t[numBytes]; + #ifdef STATIC_ONLY + uint8_t response[STATIC_ARRAY_SIZE]; + #else + uint8_t* response = new uint8_t[numBytes]; + #endif _tl->receive(response, numBytes); if((response[0] == MQTT_CONNACK << 4) && (response[1] == 2)) { uint8_t returnCode = response[3]; - delete[] response; + #ifndef STATIC_ONLY + delete[] response; + #endif return(returnCode); } - - delete[] response; + + #ifndef STATIC_ONLY + delete[] response; + #endif return(ERR_RESPONSE_MALFORMED); } int16_t MQTTClient::disconnect() { // build the DISCONNECT packet uint8_t packet[2]; - + // fixed header packet[0] = (MQTT_DISCONNECT << 4) | 0b0000; packet[1] = 0x00; - + // send MQTT packet int16_t state = _tl->send(packet, 2); if(state != ERR_NONE) { return(state); } - + // close tl connection return(_tl->closeTransportConnection()); } @@ -156,14 +172,18 @@ int16_t MQTTClient::publish(const char* topic, const char* message) { uint32_t remainingLength = (2 + topicLen) + messageLen; uint8_t encoded[] = {0, 0, 0, 0}; size_t encodedBytes = encodeLength(remainingLength, encoded); - + // build the PUBLISH packet - uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength]; - + #ifdef STATIC_ONLY + uint8_t packet[STATIC_ARRAY_SIZE]; + #else + uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength]; + #endif + // fixed header packet[0] = (MQTT_PUBLISH << 4) | 0b0000; memcpy(packet + 1, encoded, encodedBytes); - + // variable header // topic name size_t pos = encodedBytes + 1; @@ -171,19 +191,21 @@ int16_t MQTTClient::publish(const char* topic, const char* message) { packet[pos++] = topicLen & 0x00FF; memcpy(packet + pos, topic, topicLen); pos += topicLen; - + // packet ID - + // payload // message memcpy(packet + pos, message, messageLen); pos += messageLen; - + // send MQTT packet int16_t state = _tl->send(packet, 1 + encodedBytes + remainingLength); - delete[] packet; + #ifndef STATIC_ONLY + delete[] packet; + #endif return(state); - + //TODO: implement QoS > 0 and PUBACK response checking } @@ -193,21 +215,25 @@ int16_t MQTTClient::subscribe(const char* topicFilter) { uint32_t remainingLength = 2 + (2 + topicFilterLen + 1); uint8_t encoded[] = {0, 0, 0, 0}; size_t encodedBytes = encodeLength(remainingLength, encoded); - + // build the SUBSCRIBE packet - uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength]; - + #ifdef STATIC_ONLY + uint8_t packet[STATIC_ARRAY_SIZE]; + #else + uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength]; + #endif + // fixed header packet[0] = (MQTT_SUBSCRIBE << 4) | 0b0010; memcpy(packet + 1, encoded, encodedBytes); - + // variable header // packet ID size_t pos = encodedBytes + 1; uint16_t packetId = _packetId++; packet[pos++] = (packetId & 0xFF00) >> 8; packet[pos++] = packetId & 0x00FF; - + // payload // topic filter packet[pos++] = (topicFilterLen & 0xFF00) >> 8;; @@ -215,35 +241,45 @@ int16_t MQTTClient::subscribe(const char* topicFilter) { memcpy(packet + pos, topicFilter, topicFilterLen); pos += topicFilterLen; packet[pos++] = 0x00; // QoS 0 - + // send MQTT packet int16_t state = _tl->send(packet, 1 + encodedBytes + remainingLength); - delete[] packet; + #ifndef STATIC_ONLY + delete[] packet; + #endif if(state != ERR_NONE) { return(state); } - + // get the response length (MQTT SUBACK response has to be 5 bytes long for single subscription) size_t numBytes = _tl->getNumBytes(); if(numBytes != 5) { return(ERR_RESPONSE_MALFORMED_AT); } - + // read the response - uint8_t* response = new uint8_t[numBytes]; + #ifdef STATIC_ONLY + uint8_t response[STATIC_ARRAY_SIZE]; + #else + uint8_t* response = new uint8_t[numBytes]; + #endif _tl->receive(response, numBytes); if((response[0] == MQTT_SUBACK << 4) && (response[1] == 3)) { // check packet ID uint16_t receivedId = response[3] | response[2] << 8; int16_t returnCode = response[4]; - delete[] response; + #ifndef STATIC_ONLY + delete[] response; + #endif if(receivedId != packetId) { return(ERR_MQTT_UNEXPECTED_PACKET_ID); } return(returnCode); } - - delete[] response; + + #ifndef STATIC_ONLY + delete[] response; + #endif return(ERR_RESPONSE_MALFORMED); } @@ -253,87 +289,109 @@ int16_t MQTTClient::unsubscribe(const char* topicFilter) { uint32_t remainingLength = 2 + (2 + topicFilterLen); uint8_t encoded[] = {0, 0, 0, 0}; size_t encodedBytes = encodeLength(remainingLength, encoded); - + // build the UNSUBSCRIBE packet - uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength]; - + #ifdef STATIC_ONLY + uint8_t packet[STATIC_ARRAY_SIZE]; + #else + uint8_t* packet = new uint8_t[1 + encodedBytes + remainingLength]; + #endif + // fixed header packet[0] = (MQTT_UNSUBSCRIBE << 4) | 0b0010; memcpy(packet + 1, encoded, encodedBytes); - + // variable header // packet ID size_t pos = encodedBytes + 1; uint16_t packetId = _packetId++; packet[pos++] = (packetId & 0xFF00) >> 8; packet[pos++] = packetId & 0x00FF; - + // payload // topic filter packet[pos++] = (topicFilterLen & 0xFF00) >> 8;; packet[pos++] = topicFilterLen & 0x00FF; memcpy(packet + pos, topicFilter, topicFilterLen); pos += topicFilterLen; - + // send MQTT packet int16_t state = _tl->send(packet, 1 + encodedBytes + remainingLength); - delete[] packet; + #ifndef STATIC_ONLY + delete[] packet; + #endif if(state != ERR_NONE) { return(state); } - + // get the response length (MQTT UNSUBACK response has to be 4 bytes long) size_t numBytes = _tl->getNumBytes(); if(numBytes != 4) { return(ERR_RESPONSE_MALFORMED_AT); } - + // read the response - uint8_t* response = new uint8_t[numBytes]; + #ifdef STATIC_ONLY + uint8_t response[STATIC_ARRAY_SIZE]; + #else + uint8_t* response = new uint8_t[numBytes]; + #endif _tl->receive(response, numBytes); if((response[0] == MQTT_UNSUBACK << 4) && (response[1] == 2)) { // check packet ID uint16_t receivedId = response[3] | response[2] << 8; - delete[] response; + #ifndef STATIC_ONLY + delete[] response; + #endif if(receivedId != packetId) { return(ERR_MQTT_UNEXPECTED_PACKET_ID); } return(ERR_NONE); } - - delete[] response; + + #ifndef STATIC_ONLY + delete[] response; + #endif return(ERR_RESPONSE_MALFORMED); } int16_t MQTTClient::ping() { // build the PINGREQ packet uint8_t packet[2]; - + // fixed header packet[0] = (MQTT_PINGREQ << 4) | 0b0000; packet[1] = 0x00; - + // send MQTT packet int16_t state = _tl->send(packet, 2); if(state != ERR_NONE) { return(state); } - + // get the response length (MQTT PINGRESP response has to be 2 bytes long) size_t numBytes = _tl->getNumBytes(); if(numBytes != 2) { return(ERR_RESPONSE_MALFORMED_AT); } - + // read the response - uint8_t* response = new uint8_t[numBytes]; + #ifdef STATIC_ONLY + uint8_t response[STATIC_ARRAY_SIZE]; + #else + uint8_t* response = new uint8_t[numBytes]; + #endif _tl->receive(response, numBytes); if((response[0] == MQTT_PINGRESP << 4) && (response[1] == 0)) { - delete[] response; + #ifndef STATIC_ONLY + delete[] response; + #endif return(ERR_NONE); } - - delete[] response; + + #ifndef STATIC_ONLY + delete[] response; + #endif return(ERR_RESPONSE_MALFORMED); } @@ -343,42 +401,42 @@ int16_t MQTTClient::check(void (*func)(const char*, const char*)) { if(state != ERR_NONE) { return(state); } - + // check new data size_t numBytes = _tl->getNumBytes(); if(numBytes == 0) { return(ERR_MQTT_NO_NEW_PACKET_AVAILABLE); } - + // read the PUBLISH packet from server uint8_t* dataIn = new uint8_t[numBytes]; _tl->receive(dataIn, numBytes); if(dataIn[0] == MQTT_PUBLISH << 4) { // TODO: properly decode remaining length uint8_t remainingLength = dataIn[1]; - + // get the topic size_t topicLength = dataIn[3] | dataIn[2] << 8; char* topic = new char[topicLength + 1]; memcpy(topic, dataIn + 4, topicLength); topic[topicLength] = 0x00; - + // get the message size_t messageLength = remainingLength - topicLength - 2; char* message = new char[messageLength + 1]; memcpy(message, dataIn + 4 + topicLength, messageLength); message[messageLength] = 0x00; - + // execute the callback function provided by user func(topic, message); - + delete[] topic; delete[] message; delete[] dataIn; return(ERR_NONE); } delete[] dataIn; - + return(ERR_MQTT_NO_NEW_PACKET_AVAILABLE); } diff --git a/src/protocols/PhysicalLayer.cpp b/src/protocols/PhysicalLayer.cpp index 23fb798c..d27735bd 100644 --- a/src/protocols/PhysicalLayer.cpp +++ b/src/protocols/PhysicalLayer.cpp @@ -19,7 +19,11 @@ int16_t PhysicalLayer::transmit(__FlashStringHelper* fstr, uint8_t addr) { } // dynamically allocate memory - char* str = new char[len]; + #ifdef STATIC_ONLY + char str[STATIC_ARRAY_SIZE]; + #else + char* str = new char[len]; + #endif // copy string from flash p = reinterpret_cast(fstr); @@ -29,7 +33,9 @@ int16_t PhysicalLayer::transmit(__FlashStringHelper* fstr, uint8_t addr) { // transmit string int16_t state = transmit(str, addr); - delete[] str; + #ifndef STATIC_ONLY + delete[] str; + #endif return(state); } @@ -62,10 +68,14 @@ int16_t PhysicalLayer::readData(String& str, size_t len) { } // build a temporary buffer - uint8_t* data = new uint8_t[length + 1]; - if(!data) { - return(ERR_MEMORY_ALLOCATION_FAILED); - } + #ifdef STATIC_ONLY + uint8_t data[STATIC_ARRAY_SIZE + 1]; + #else + uint8_t* data = new uint8_t[length + 1]; + if(!data) { + return(ERR_MEMORY_ALLOCATION_FAILED); + } + #endif // read the received data state = readData(data, length); @@ -79,7 +89,9 @@ int16_t PhysicalLayer::readData(String& str, size_t len) { } // deallocate temporary buffer - delete[] data; + #ifndef STATIC_ONLY + delete[] data; + #endif return(state); } @@ -96,10 +108,14 @@ int16_t PhysicalLayer::receive(String& str, size_t len) { } // build a temporary buffer - uint8_t* data = new uint8_t[length + 1]; - if(!data) { - return(ERR_MEMORY_ALLOCATION_FAILED); - } + #ifdef STATIC_ONLY + uint8_t data[STATIC_ARRAY_SIZE + 1]; + #else + uint8_t* data = new uint8_t[length + 1]; + if(!data) { + return(ERR_MEMORY_ALLOCATION_FAILED); + } + #endif // attempt packet reception state = receive(data, length); @@ -118,7 +134,9 @@ int16_t PhysicalLayer::receive(String& str, size_t len) { } // deallocate temporary buffer - delete[] data; + #ifndef STATIC_ONLY + delete[] data; + #endif return(state); } diff --git a/src/protocols/RTTY.cpp b/src/protocols/RTTY.cpp index e0f6d90b..c56f0b0b 100644 --- a/src/protocols/RTTY.cpp +++ b/src/protocols/RTTY.cpp @@ -2,20 +2,20 @@ ITA2String::ITA2String(char c) { _len = 1; - _str = new char[1]; _str[0] = c; _ita2Len = 0; } ITA2String::ITA2String(const char* str) { _len = strlen(str); - _str = new char[_len]; strcpy(_str, str); _ita2Len = 0; } ITA2String::~ITA2String() { - delete[] _str; + #ifndef STATIC_ONLY + delete[] _str; + #endif } size_t ITA2String::length() { @@ -32,7 +32,11 @@ size_t ITA2String::length() { uint8_t* ITA2String::byteArr() { // create temporary array 2x the string length (figures may be 3 bytes) - uint8_t* temp = new uint8_t[_len*2 + 1]; + #ifdef STATIC_ONLY + uint8_t temp[STATIC_ARRAY_SIZE*2 + 1]; + #else + uint8_t* temp = new uint8_t[_len*2 + 1]; + #endif size_t arrayLen = 0; bool flagFigure = false; @@ -75,7 +79,9 @@ uint8_t* ITA2String::byteArr() { uint8_t* arr = new uint8_t[arrayLen]; memcpy(arr, temp, arrayLen); - delete[] temp; + #ifndef STATIC_ONLY + delete[] temp; + #endif return(arr); } @@ -202,7 +208,11 @@ size_t RTTYClient::print(__FlashStringHelper* fstr) { } // dynamically allocate memory - char* str = new char[len]; + #ifdef STATIC_ONLY + char str[STATIC_ARRAY_SIZE]; + #else + char* str = new char[len]; + #endif // copy string from flash p = reinterpret_cast(fstr); @@ -217,7 +227,9 @@ size_t RTTYClient::print(__FlashStringHelper* fstr) { } else if((_encoding == ASCII) || (_encoding == ASCII_EXTENDED)) { n = RTTYClient::write((uint8_t*)str, len); } - delete[] str; + #ifndef STATIC_ONLY + delete[] str; + #endif return(n); } diff --git a/src/protocols/RTTY.h b/src/protocols/RTTY.h index 6a4e9332..06aeac55 100644 --- a/src/protocols/RTTY.h +++ b/src/protocols/RTTY.h @@ -58,7 +58,11 @@ class ITA2String { uint8_t* byteArr(); private: - char* _str; + #ifdef STATIC_ONLY + char _str[STATIC_ARRAY_SIZE]; + #else + char* _str = new char[1]; + #endif size_t _len; size_t _ita2Len;