LoboMQ
Loading...
Searching...
No Matches
BrokerSDUtils.cpp
Go to the documentation of this file.
1
10
11String replaceChars(const char *str) {
12 String result = "";
13 while (*str) {
14 switch (*str) {
15 /* Converted special chars to escaped unicode chars, its the only way to
16 properly use it for filenames
17 https://www.utf8-chartable.de/unicode-utf8-table.pl?utf8=string-literal */
18 case '<': result += "\xC2\xAB"; break; //«
19 case '>': result += "\xC2\xBB"; break; //»
20 case ':': result += "\xC3\xB7"; break; //÷
21 case '"': result += "\xC2\xAA"; break; //ª
22 case '/': result += "\xE2\x88\x9A"; break; //√
23 case '\\': result += "\xC3\xAC"; break; //ì
24 case '|': result += "\xE2\x94\x82"; break; //│
25 case '?': result += "\xC2\xBF"; break; //¿
26 case '*': result += "\xC2\xBA"; break; //º
27 default: result += *str; break;
28 }
29 str++;
30 }
31 return result;
32}
33
34bool initializeSDCard(int csPin, Elog *logger, SemaphoreHandle_t *mutex, TickType_t delay) {
35 if (!SD.begin(csPin)) {
36 logger->log(ERROR, "[BT SD] Couldn't initialize SD card for persistence.");
37 return false;
38 }
39
40 if (!xSemaphoreTake(*mutex, delay)) {
41 logger->log(ERROR, "[BT SD] Couldn't take mutex for initialization.");
42 return false;
43 }
44
45 //Creates all folders in path
46 int index = 0;
47 while (index != -1) {
48 index = String(FILE_PATH).indexOf("/", index+1); //Finds "/" position
49 if (index>0) {
50 String subpath = String(FILE_PATH).substring(0, index); //Gets subpath until next "/"
51 if (!SD.exists(subpath) and !SD.mkdir(subpath)) { //If subpath does not exist, creates it
52 logger->log(ERROR, "[BT SD] Couldn't create folder (%s).", subpath.c_str());
53 xSemaphoreGive(*mutex); //release mutex because of error
54 return false;
55 }
56 }
57 }
58
59 //Creates deepest folder
60 if (!SD.exists(FILE_PATH) and !SD.mkdir(FILE_PATH)) {
61 logger->log(ERROR, "[BT SD] Couldn't create folder (%s).", String(FILE_PATH).c_str());
62 xSemaphoreGive(*mutex); //release mutex because of error
63 return false;
64 }
65 xSemaphoreGive(*mutex); //release mutex, success
66 return true;
67}
68
69void restoreBTs(std::vector<BrokerTopic> *topicsVector, Elog *logger, SemaphoreHandle_t *mutex,
70 TickType_t delay) {
71 if (!xSemaphoreTake(*mutex, delay)) {
72 logger->log(ERROR, "[BT SD] Couldn't take mutex for BTs restoration.");
73 return;
74 }
75
76 File dir = SD.open(FILE_PATH);
77 //go through every file at folder FILE_PATH
78 if (!dir) {
79 logger->log(ERROR, "[BT SD] Couldn't open main directory %s.", FILE_PATH);
80 } else {
81 while (File file = dir.openNextFile()) {
82 String filename = file.name();
83 if (!file.isDirectory() && filename.endsWith(FILE_FORMAT)) {
84 const char *topic;
85 //std::vector<std::array<uint8_t, 6>> subscribers;
86
87 JsonDocument doc;
88 DeserializationError error = deserializeJson(doc, file);
89 if (error) {
90 logger->log(ERROR, "[BT SD] Error parsing JSON file %s.", file.name());
91 continue;
92 }
93
94 topic = doc["topic"];
95 JsonArray subscribersArray = doc["subscribers"];
96
97 if (subscribersArray.size() == 0) {
98 logger->log(WARNING, "[BT SD] No subscribers found in topic '%s' of the SD card, skipped.", topic);
99 continue;
100 }
101
102 BrokerTopic newTopic(logger, topic);
103
104 for (const auto &mac : subscribersArray) {
105 std::array<uint8_t, 6> macArray;
106 sscanf(mac, "%02X:%02X:%02X:%02X:%02X:%02X\n",
107 &macArray[0], &macArray[1], &macArray[2], &macArray[3], &macArray[4], &macArray[5]);
108 //subscribers.push_back(macArray);
109 newTopic.subscribe(macArray);
110 }
111 String filename = file.name();
112 filename.replace(FILE_FORMAT, "");
113 newTopic.setFilename(filename.c_str());
114 topicsVector->push_back(newTopic);
115 logger->log(INFO, "[BT SD] Created topic '%s' found on SD card.", topic);
116 }
117 file.close();
118 }
119 dir.close();
120 }
121 xSemaphoreGive(*mutex);
122}
123
124void writeBTToFile(BrokerTopic* brokerTopic, Elog* logger, SemaphoreHandle_t *mutex, TickType_t delay) {
125 JsonDocument doc;
126 doc["topic"] = brokerTopic->getTopic();
127 JsonArray subscribersArray = doc["subscribers"].to<JsonArray>();
128 for (const auto& mac : brokerTopic->getSubscribers()) {
129 char macChar[18];
130 snprintf(macChar, sizeof(macChar), "%02X:%02X:%02X:%02X:%02X:%02X\n",
131 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
132 subscribersArray.add(macChar);
133 }
134
135 String fullFilepath = (String(FILE_PATH)+"/"+brokerTopic->getFilename()+String(FILE_FORMAT));
136
137 if (!xSemaphoreTake(*mutex, delay)) {
138 logger->log(ERROR, "[BT SD] Couldn't take mutex for BT file write.");
139 return;
140 }
141
142 File file = SD.open(fullFilepath, FILE_WRITE);
143 if (!file) {
144 logger->log(ERROR, "[BT SD] Couldn't open file for writing (%s).", fullFilepath.c_str());
145 } else {
146 serializeJsonPretty(doc, file);
147 logger->log(DEBUG, "[BT SD] Wrote topic '%s' to file '%s' successfully.", brokerTopic->getTopic(),
148 (brokerTopic->getFilename()+String(FILE_FORMAT)));
149 file.close();
150 }
151 xSemaphoreGive(*mutex);
152}
153
154void deleteBTFile(const char* filename, Elog* logger, SemaphoreHandle_t *mutex, TickType_t delay) {
155 if (!xSemaphoreTake(*mutex, delay)) {
156 logger->log(ERROR, "[BT SD] Couldn't take mutex for BT file deletion.");
157 return;
158 }
159
160 String fullFilepath = (String(FILE_PATH)+"/"+filename+String(FILE_FORMAT));
161 File file = SD.open(fullFilepath, FILE_WRITE);
162 if (!file) {
163 logger->log(ERROR, "[BT SD] Couldn't open file for deletion (%s).", fullFilepath.c_str());
164 } else {
165 if (!SD.remove(file.path())) {
166 logger->log(ERROR, "[BT SD] Couldn't delete file (%s).", fullFilepath.c_str());
167 } else {
168 logger->log(DEBUG, "[BT SD] Deleted file %s successfully.", file.name());
169 }
170 file.close();
171 }
172 xSemaphoreGive(*mutex);
173}