Skip to content
Snippets Groups Projects
Commit cfcf481a authored by Zoe Pfister's avatar Zoe Pfister :speech_balloon:
Browse files

Merge branch '29-resending-of-data-if-network-connection-was-lost' into 'develop'

Resend Data capabilities

See merge request !22
parents 3935b909 38965ef1
No related branches found
No related tags found
2 merge requests!39Merge Develop into Main,!22Resend Data capabilities
//
// Created by cynthya on 1/5/23.
//
#include "ResendManager.h"
#include "Utilities.h"
void ResendManager::init() {
createResendDirectory();
// log
uint lastResendFileId = getLastResendFileId();
nextResendFileId = lastResendFileId + 1;
esp_log_write(ESP_LOG_INFO, "ResendManager", "nextResendFileId: %d\n", nextResendFileId);
}
uint ResendManager::getLastResendFileId() const { // get the next file id to be resend
auto filesInDirectory = getFilesInDirectory(resendDirectoryPath);
// convert the file names to uint
std::list<uint> fileUintIDs;
try {
for (const auto &fileName : filesInDirectory) {
fileUintIDs.emplace_back(std::stoul(fileName.c_str()));
}
} catch (std::invalid_argument &e) {
esp_log_write(ESP_LOG_ERROR, "getLastResendFileId", "Failed to convert file name to uint\n");
throw;
}
// get the max
uint max = 0;
for (const auto &fileID : fileUintIDs) {
if (fileID > max) {
max = fileID;
}
}
return max;
}
void ResendManager::createResendDirectory() const { // create directory if it doesn't exist
createDirectory("/resend");
}
void ResendManager::storeForResend(const String &messageToBeSend) {
// create file
String filename = String(nextResendFileId);
writeFile(messageToBeSend, resendDirectoryPath + "/" + filename);
ResendManager::incrementCount();
}
std::optional<ResendPointType> ResendManager::loadNextToBeResendMessage() {
// get first file in resend directory
auto filename = getFirstFileNameInDirectory(resendDirectoryPath.c_str());
if (filename.has_value()) {
// read file
auto message = readFile(resendDirectoryPath + "/" + filename.value().c_str());
return ResendPointType{message, filename.value()};
}
return std::nullopt;
}
void ResendManager::deleteResendMessage(const String &filename) {
auto filePath = resendDirectoryPath + "/" + filename;
if (SD.remove(filePath.c_str())) {
esp_log_write(ESP_LOG_INFO, "ResendManager", "Deleted file: %s\n", filePath.c_str());
} else {
esp_log_write(ESP_LOG_ERROR, "ResendManager", "Failed to delete file: %s\n", filePath.c_str());
throw;
}
}
//
// Created by cynthya on 1/5/23.
//
#ifndef HOST_CENTRAL_MAST_RESENDMANAGER_H
#define HOST_CENTRAL_MAST_RESENDMANAGER_H
#include "ResendPointType.h"
#include "SD.h"
#include "Utilities.h"
#include <Arduino.h>
#include <cstdio>
class ResendManager {
public:
// File name (as uint) of the next file to be re-send (i.e. a counter of files to be resend). Max value is
// 4'294'967'295
void storeForResend(const String &messageToBeSend);
// I am making this an optional since i want to avoid creating a 'hasNextToBeResend' method since that would require
// another fs operation. If this method returns std::nullopt, it means that there is no file to be resend.
std::optional<ResendPointType> loadNextToBeResendMessage();
void deleteResendMessage(const String &filename);
void init();
private:
const String resendDirectoryPath = "/resend";
uint nextResendFileId = 0;
void incrementCount() { nextResendFileId++; }
void createResendDirectory() const;
uint getLastResendFileId() const;
};
#endif // HOST_CENTRAL_MAST_RESENDMANAGER_H
//
// Created by cynthya on 1/5/23.
//
#ifndef HOST_CENTRAL_MAST_RESENDPOINTTYPE_H
#define HOST_CENTRAL_MAST_RESENDPOINTTYPE_H
#include <Arduino.h>
struct ResendPointType {
String message;
String filename;
};
#endif // HOST_CENTRAL_MAST_RESENDPOINTTYPE_H
//
// Created by zoe on 1/12/23.
//
#ifndef HOST_CENTRAL_MAST_DEFINITIONS_H
#define HOST_CENTRAL_MAST_DEFINITIONS_H
#include "Arduino.h"
#define uS_TO_S_FACTOR 1000000ULL // Conversion factor for micro seconds to seconds
#define TIME_TO_SLEEP 5 // Time ESP32 will go to sleep (in seconds)
#define UART_BAUD 115200
#define PIN_DTR 25
#define PIN_TX 27
#define PIN_RX 26
#define PWR_PIN 4
#define SD_MISO 2
#define SD_MOSI 15
#define SD_SCLK 14
#define SD_CS 13
#define LED_PIN 12
const String INFLUXDB_TOKEN =
"dUh2gbVLv7e3egqocxriDsJQNUacA9qZ5YXsYtdnVAglnHgy4nx-jDVO7nGlSF34BosfnuwnUDaviC7dQeC5RQ==";
#endif // HOST_CENTRAL_MAST_DEFINITIONS_H
//
// Created by zoe on 1/12/23.
//
#ifndef HOST_CENTRAL_MAST_SDCARDEXCEPTION_H
#define HOST_CENTRAL_MAST_SDCARDEXCEPTION_H
#include <Arduino.h>
#include <exception>
// create a custom exception type called SD Card Exception
class SDCardException : public std::exception {
public:
SDCardException(const String &message) : message(message) {}
const char *what() const noexcept override { return message.c_str(); }
private:
String message;
};
#endif // HOST_CENTRAL_MAST_SDCARDEXCEPTION_H
//
// Created by zoe on 1/12/23.
//
#ifndef HOST_CENTRAL_MAST_SDSETUPEXCEPTION_H
#define HOST_CENTRAL_MAST_SDSETUPEXCEPTION_H
#include <Arduino.h>
#include <exception>
// create a custom exception type called SD Setup Exception
class SDSetupException : public std::exception {
public:
SDSetupException(const String &message) : message(message) {}
const char *what() const noexcept override { return message.c_str(); }
private:
String message;
};
#endif // HOST_CENTRAL_MAST_SDSETUPEXCEPTION_H
//
// Created by zoe on 1/9/23.
//
#include "Utilities.h"
void setupSDCard();
void saveStringToSDCard(const std::string &dataString);
std::list<String> getFilesInDirectory(const String &dirname) {
std::list<String> files;
File dir = openDirectory(dirname);
while (true) {
File nextFile = dir.openNextFile();
if (!nextFile) {
break;
}
if (!nextFile.isDirectory()) {
files.emplace_back(nextFile.name());
}
nextFile.close();
}
return files;
}
std::optional<String> getLastFileInDirectory(const String &dirname) {
File root = openDirectory(dirname);
root.rewindDirectory();
File file = root.openNextFile();
while (file) {
File nextFile = root.openNextFile();
if (!nextFile) {
break;
}
file = nextFile;
}
// log
if (file) {
esp_log_write(ESP_LOG_INFO, "getLastFileInDirectory", "Last file name: %s\n", file.name());
return file.name();
} else {
esp_log_write(ESP_LOG_INFO, "getLastFileInDirectory", "No file found\n");
return std::nullopt;
}
}
File openDirectory(const String &dirname) {
File root = SD.open(dirname);
if (!root) {
esp_log_write(ESP_LOG_ERROR, "openDirectory", "Failed to open directory\n");
throw;
}
if (!root.isDirectory()) {
esp_log_write(ESP_LOG_ERROR, "openDirectory", "Not a directory\n");
throw;
}
return root;
}
std::optional<String> getFirstFileNameInDirectory(const String &dirname) {
File root = openDirectory(dirname);
root.rewindDirectory();
File file = root.openNextFile();
if (file) {
esp_log_write(ESP_LOG_INFO, "getFirstFileNameInDirectory", "file found: %s\n", file.name());
return file.name();
} else {
esp_log_write(ESP_LOG_INFO, "getFirstFileNameInDirectory", "no file found\n");
return std::nullopt;
}
}
File openForWrite(const String &filePath) {
File file = SD.open(filePath, FILE_WRITE);
if (!file) {
esp_log_write(ESP_LOG_ERROR, "SD", "Failed to open file for writing\n");
throw;
}
return file;
}
File openForRead(const String &filePath) {
File file = SD.open(filePath, FILE_READ);
if (!file) {
esp_log_write(ESP_LOG_ERROR, "SD", "Failed to open file for reading\n");
throw;
}
return file;
}
void writeFile(const String &messageToBeSend, const String &filePath) {
File file = openForWrite(filePath);
if (file.print(messageToBeSend)) {
esp_log_write(ESP_LOG_INFO, "SD", "File written %s\n", filePath.c_str());
} else {
esp_log_write(ESP_LOG_ERROR, "SD", "Write failed %s\n", filePath.c_str());
throw;
}
file.close();
}
String readFile(const String &filePath) {
File file = openForRead(filePath);
String ret;
while (file.available()) {
ret += (char)file.read();
}
file.close();
return ret;
}
void createDirectory(const String &dirname) {
if (!SD.exists(dirname)) {
SD.mkdir(dirname);
esp_log_write(ESP_LOG_INFO, "createDirectory", "Created directory: %s\n", dirname.c_str());
} else {
esp_log_write(ESP_LOG_WARN, "createDirectory", "Directory already exists\n");
}
}
void setupSDCard(int MISO, int MOSI, int SCLK, int CS) {
SPI.begin(SCLK, MISO, MOSI, CS);
if (!SD.begin(CS)) {
esp_log_write(ESP_LOG_ERROR, "Utilities", "Card MOUNT FAIL\n");
throw SDSetupException("Card MOUNT FAIL");
} else {
uint32_t cardSize = SD.cardSize() / (1024 * 1024);
String sdcardSizeString = "SDCard Size: " + String(cardSize) + "MB";
esp_log_write(ESP_LOG_DEBUG, "Utilities", "%s\n", sdcardSizeString.c_str());
}
}
void saveStringToSDCard(const std::string &dataString) {
File dataFile = SD.open("/datalog.txt", FILE_APPEND);
// if the file is available, write to it:
if (dataFile) {
if (dataString.length() > 0) {
dataFile.println(dataString.c_str());
}
dataFile.close();
}
// if the file isn't open, pop up an error:
else {
esp_log_write(ESP_LOG_ERROR, "Utilities", "error opening datalog.txt\n");
throw SDCardException("error opening datalog.txt");
}
}
\ No newline at end of file
//
// Created by zoe on 1/9/23.
//
#ifndef HOST_CENTRAL_MAST_UTILITIES_H
#define HOST_CENTRAL_MAST_UTILITIES_H
#include "SD.h"
#include "SDCardException.h"
#include "SDSetupException.h"
#include <Arduino.h>
#include <Definitions.h>
#include <WString.h>
#include <list>
File openDirectory(const String &dirname);
std::list<String> getFilesInDirectory(const String &dirname);
std::optional<String> getFirstFileNameInDirectory(const String &dirname);
std::optional<String> getLastFileInDirectory(const String &dirname);
void writeFile(const String &messageToBeSend, const String &filePath);
String readFile(const String &filePath);
void createDirectory(const String &dirname);
void setupSDCard(int MISO, int MOSI, int SCLK, int CS);
void saveStringToSDCard(const std::string &dataString);
#endif // HOST_CENTRAL_MAST_UTILITIES_H
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment