#include <SD.h>
#include <ESP8266WebServer.h>
#include <SPI.h>
#include <IPAddress.h>
/* How IPAddress is defined in IPAddress.h */
//class IPAddress: public Printable
//{
//private:
// union {
// uint8_t bytes[4]; // IPv4 address
// uint32_t dword;
// } _address;
//
// // Access the raw byte array containing the address. Because this returns a pointer
// // to the internal structure rather than a copy of the address this function should only
// // be used when you know that the usage of the returned uint8_t* will be transient and not
// // stored.
// uint8_t* raw_address()
// {
// return _address.bytes;
// }
#define MAX_CALLERS 300
typedef struct
{
IPAddress iaddr; // Little Endian
IPAddress iaddrBE; // Big Endian
long count;
} IPCallers;
IPCallers MyCallers[MAX_CALLERS];
IPCallers SDRead[MAX_CALLERS];
int WebRequests;
const char *STestFN = "test.txt";
const char *StuctFN = "Struct.txt";
String buffer;
IPAddress ip1( 10, 210, 0, 1);
IPAddress ip2(201, 2, 200, 22);
IPAddress ip3(123, 211, 135, 003);
IPAddress ip4( 96, 4, 4, 4);
int iTemp;
bool SD_Valid = true; // Until proven otherwise.
#define chipSelect D8
// Pin used for CS for the SD shield.
IPAddress ipTemp, ipTempBE;
uint32_t myLocalIP;
File myFile;
void setup() {
//Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial) {
;
}
Serial.print("\nInitializing SD card...");
if (!SD.begin(D8)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
//Initialize fields
MyCallers[0].iaddr = ip1; MyCallers[1].iaddr = ip2;
MyCallers[2].iaddr = ip3; MyCallers[3].iaddr = ip4;
MyCallers[0].count = 10; MyCallers[1].count = 9;
MyCallers[2].count = 8; MyCallers[3].count = 7;
WebRequests = 4;
for (iTemp = 0; iTemp < WebRequests; iTemp++) {
MyCallers[iTemp].iaddrBE[0] = MyCallers[iTemp].iaddr[3];
MyCallers[iTemp].iaddrBE[1] = MyCallers[iTemp].iaddr[2];
MyCallers[iTemp].iaddrBE[2] = MyCallers[iTemp].iaddr[1];
MyCallers[iTemp].iaddrBE[3] = MyCallers[iTemp].iaddr[0];
}
PrintOrigStruct();
Serial.println("By Count Ascending");
SortCtA();
PrintOrigStruct();
Serial.println("By Count Descending");
SortCtD();
PrintOrigStruct();
Serial.println("By IP Ascending");
SortIPA();
PrintOrigStruct();
Serial.println("By IP Descending");
SortIPD();
PrintOrigStruct();
Serial.println("Checking if file exists and removing if so.");
if (SD.exists(STestFN))
{
Serial.println("File exists, removing it now."); yield();
SD.remove("test.txt");
}
//Open the file. Note that only one file can be open at a time,
//so you have to close this one before opening another.
myFile = SD.open(STestFN, FILE_WRITE);
//If the file opened okay, write to it:
if (myFile) {
Serial.print("Writing to test.txt...");
myFile.println("testing 1, 2, 3.");
//close the file
myFile.close();
Serial.println("done.");
} else {
//if the file didn't open, print an error
Serial.println("error opening test.txt");
}
//Now open the file for reading:
myFile = SD.open(STestFN);
if (myFile) {
Serial.println("Reading test.txt:");
//Read from the file until there's nothing else in it
while (myFile.available()) {
Serial.print(">"); Serial.print(myFile.readStringUntil('\n'));
}
// iTemp = myFile.read());
//Close the file
myFile.close();
} else {
//If the file didn't open, print an error
Serial.println("error opening test.txt");
}
WriteIP(); ReadIP();
}
void WriteIP() {
Serial.println("Testing if file exists."); yield();
if (SD.exists("Struct.txt"));
{
Serial.println("File exists, removing it now."); yield();
SD.remove("Struct.txt");
}
Serial.println("Opening file now."); yield();
File dataFile = SD.open(StuctFN, FILE_WRITE);
if (dataFile) { // Only try to write it if it opened successfully.
Serial.println("Writing file data 1.");
dataFile.println(WebRequests);
for (iTemp = 0; iTemp < WebRequests; iTemp++) {
// myLocalIP = (uint32_t) MyCallers[iTemp].iaddr;
Serial.print("Numeric version of MyCallers[itemp].iaddr = "); Serial.println(myLocalIP);
// dataFile.println(myLocalIP);
dataFile.println((uint32_t) MyCallers[iTemp].iaddr);
dataFile.println(MyCallers[iTemp].count);
}
dataFile.close(); yield();
} else { // or if datafile did not open...
Serial.print("Error opening "); Serial.println(STestFN); return;
} // if (datafile)}
}
void ReadIP() {
int linesToRead;
int linesRead = 0;
long ct;
myFile = SD.open(StuctFN);
if (myFile) {
Serial.println("Reading Struct.txt:");
//Read from the file until there's nothing else in it
// while (myFile.available()) Serial.write(myFile.read());
if (myFile.available()) {
buffer = myFile.readStringUntil('\n');
if (isValidNumber(buffer)) linesToRead = buffer.toInt();
Serial.print("Converted count: "); Serial.println(linesToRead);
}
while (myFile.available()) {
buffer = myFile.readStringUntil('\n');
//Read first IP as UL
Serial.print("Line read: '");Serial.print(buffer); Serial.println("'"); yield();
if (isValidNumber(buffer)) {
myLocalIP = buffer.toInt();
SDRead[linesRead].iaddr = (uint32_t)myLocalIP;
}
buffer = myFile.readStringUntil('\n');
//Read first count as int
Serial.print("Line read: '");Serial.print(buffer); Serial.println("'"); yield();
if (isValidNumber(buffer)) {
ct = buffer.toInt();
SDRead[linesRead].count = ct;
}
SDRead[linesRead].iaddrBE[0] = SDRead[linesRead].iaddr[3];
SDRead[linesRead].iaddrBE[1] = SDRead[linesRead].iaddr[2];
SDRead[linesRead].iaddrBE[2] = SDRead[linesRead].iaddr[1];
SDRead[linesRead].iaddrBE[3] = SDRead[linesRead].iaddr[0];
linesRead++;
}
//Close the file
myFile.close();
} else {
//If the file didn't open, print an error
Serial.println("error opening test.txt");
}
PrintReadStruct();
}
void PrintOrigStruct() {
for (iTemp = 0; iTemp < WebRequests; iTemp++) {
Serial.print(iTemp); Serial.print(">");
Serial.print(MyCallers[iTemp].iaddr); Serial.print("\t- ");
Serial.print(MyCallers[iTemp].iaddrBE); Serial.print("\t ts:");
Serial.print(MyCallers[iTemp].iaddrBE.toString());
Serial.print("\t("); Serial.print(MyCallers[iTemp].count);
Serial.println(" times.)"); yield();
}
}
void PrintReadStruct() {
for (iTemp = 0; iTemp < WebRequests; iTemp++) {
Serial.print(iTemp); Serial.print(">");
Serial.print(SDRead[iTemp].iaddr); Serial.print("\t- ");
Serial.print(SDRead[iTemp].iaddrBE); Serial.print("\t ts:");
Serial.print(SDRead[iTemp].iaddrBE.toString());
Serial.print("\t("); Serial.print(SDRead[iTemp].count);
Serial.println(" times.)"); yield();
}
}
void SortCtD() {
IPAddress ipTemp;
long ctTemp;
for (iTemp = 0; iTemp < (WebRequests - 1); iTemp++) {
for (int iSort = 0; iSort < WebRequests - iTemp - 1; iSort++) {
if (MyCallers[iSort].count < MyCallers[iSort + 1].count) {
ipTemp = MyCallers[iSort].iaddr;
ipTempBE = MyCallers[iSort].iaddrBE;
ctTemp = MyCallers[iSort].count;
MyCallers[iSort].iaddr = MyCallers[iSort + 1].iaddr;
MyCallers[iSort].iaddrBE = MyCallers[iSort + 1].iaddrBE;
MyCallers[iSort].count = MyCallers[iSort + 1].count;
MyCallers[iSort + 1].iaddr = ipTemp;
MyCallers[iSort + 1].iaddrBE = ipTempBE;
MyCallers[iSort + 1].count = ctTemp;
yield();
}
}
}
}
void SortCtA() {
IPAddress ipTemp;
long ctTemp;
for (iTemp = 0; iTemp < (WebRequests - 1); iTemp++) {
for (int iSort = 0; iSort < WebRequests - iTemp - 1; iSort++) {
if (MyCallers[iSort].count > MyCallers[iSort + 1].count) {
ipTemp = MyCallers[iSort].iaddr;
ipTempBE = MyCallers[iSort].iaddrBE;
ctTemp = MyCallers[iSort].count;
MyCallers[iSort].iaddr = MyCallers[iSort + 1].iaddr;
MyCallers[iSort].iaddrBE = MyCallers[iSort + 1].iaddrBE;
MyCallers[iSort].count = MyCallers[iSort + 1].count;
MyCallers[iSort + 1].iaddr = ipTemp;
MyCallers[iSort + 1].iaddrBE = ipTempBE;
MyCallers[iSort + 1].count = ctTemp;
yield();
}
}
}
}
void SortIPA() {
IPAddress ipTemp;
long ctTemp;
for (iTemp = 0; iTemp < (WebRequests - 1); iTemp++) {
for (int iSort = 0; iSort < WebRequests - iTemp - 1; iSort++) {
if (MyCallers[iSort].iaddrBE > MyCallers[iSort + 1].iaddrBE) {
ipTemp = MyCallers[iSort].iaddr;
ipTempBE = MyCallers[iSort].iaddrBE;
ctTemp = MyCallers[iSort].count;
MyCallers[iSort].iaddr = MyCallers[iSort + 1].iaddr;
MyCallers[iSort].iaddrBE = MyCallers[iSort + 1].iaddrBE;
MyCallers[iSort].count = MyCallers[iSort + 1].count;
MyCallers[iSort + 1].iaddr = ipTemp;
MyCallers[iSort + 1].iaddrBE = ipTempBE;
MyCallers[iSort + 1].count = ctTemp;
yield();
}
}
}
}
void SortIPD() {
IPAddress ipTemp;
long ctTemp;
for (iTemp = 0; iTemp < (WebRequests - 1); iTemp++) {
for (int iSort = 0; iSort < WebRequests - iTemp - 1; iSort++) {
if (MyCallers[iSort].iaddrBE < MyCallers[iSort + 1].iaddrBE) {
ipTemp = MyCallers[iSort].iaddr;
ipTempBE = MyCallers[iSort].iaddrBE;
ctTemp = MyCallers[iSort].count;
MyCallers[iSort].iaddr = MyCallers[iSort + 1].iaddr;
MyCallers[iSort].iaddrBE = MyCallers[iSort + 1].iaddrBE;
MyCallers[iSort].count = MyCallers[iSort + 1].count;
MyCallers[iSort + 1].iaddr = ipTemp;
MyCallers[iSort + 1].iaddrBE = ipTempBE;
MyCallers[iSort + 1].count = ctTemp;
yield();
}
}
}
}
boolean isValidNumber(String str){
for(byte i = 0; i < str.length(); i++)
if(isDigit(str.charAt(i))) return true;
return false;
}
void loop() { }
So I took a Wemos D1 from the shelf, put it on a doubler-board with an SD-shield (inserted a 2GB microSD-card) at its side.
This is what my compiler is saying (don't mind the warnings, that's because I'm using the Git-master of the ESP8266 Arduino-core):
WARNING: library SPI claims to run on (esp8266) architecture(s) and may be incompatible with your current board which runs on (Arduino) architecture(s).
WARNING: library ESP8266WebServer claims to run on (esp8266) architecture(s) and may be incompatible with your current board which runs on (Arduino) architecture(s).
WARNING: library ESP8266WiFi claims to run on (esp8266) architecture(s) and may be incompatible with your current board which runs on (Arduino) architecture(s).
Archiving built core (caching) in: C:\Users\QUICKF~1\AppData\Local\Temp\arduino_cache_575934\core\core_esp8266com_Arduino_d1_mini_CpuFrequency_80,UploadSpeed_921600,FlashSize_4M3M_21655eb80f1d4fdd8e4dada24d8451b9.a
Sketch uses 256177 bytes (24%) of program storage space. Maximum is 1044464 bytes.
Global variables use 46688 bytes (56%) of dynamic memory, leaving 35232 bytes for local variables. Maximum is 81920 bytes.
Uploading 260320 bytes from C:\Users\QUICKF~1\AppData\Local\Temp\arduino_build_266395/sketch_oct17a.ino.bin to flash at 0x00000000
................................................................................ [ 31% ]
................................................................................ [ 62% ]
................................................................................ [ 94% ]
............... [ 100% ]
After a succesful flash, the code runs and this is what my terminal says:
Initializing SD card...initialization done.
0>10.210.0.1 - 1.0.210.10 ts:1.0.210.10 (10 times.)
1>201.2.200.22 - 22.200.2.201 ts:22.200.2.201 (9 times.)
2>123.211.135.3 - 3.135.211.123 ts:3.135.211.123 (8 times.)
3>96.4.4.4 - 4.4.4.96 ts:4.4.4.96 (7 times.)
By Count Ascending
0>96.4.4.4 - 4.4.4.96 ts:4.4.4.96 (7 times.)
1>123.211.135.3 - 3.135.211.123 ts:3.135.211.123 (8 times.)
2>201.2.200.22 - 22.200.2.201 ts:22.200.2.201 (9 times.)
3>10.210.0.1 - 1.0.210.10 ts:1.0.210.10 (10 times.)
By Count Descending
0>10.210.0.1 - 1.0.210.10 ts:1.0.210.10 (10 times.)
1>201.2.200.22 - 22.200.2.201 ts:22.200.2.201 (9 times.)
2>123.211.135.3 - 3.135.211.123 ts:3.135.211.123 (8 times.)
3>96.4.4.4 - 4.4.4.96 ts:4.4.4.96 (7 times.)
By IP Ascending
0>10.210.0.1 - 1.0.210.10 ts:1.0.210.10 (10 times.)
1>96.4.4.4 - 4.4.4.96 ts:4.4.4.96 (7 times.)
2>123.211.135.3 - 3.135.211.123 ts:3.135.211.123 (8 times.)
3>201.2.200.22 - 22.200.2.201 ts:22.200.2.201 (9 times.)
By IP Descending
0>201.2.200.22 - 22.200.2.201 ts:22.200.2.201 (9 times.)
1>123.211.135.3 - 3.135.211.123 ts:3.135.211.123 (8 times.)
2>96.4.4.4 - 4.4.4.96 ts:4.4.4.96 (7 times.)
3>10.210.0.1 - 1.0.210.10 ts:1.0.210.10 (10 times.)
Checking if file exists and removing if so.
Writing to test.txt...done.
Reading test.txt:
>testing 1, 2, 3.
Testing if file exists.
File exists, removing it now.
Opening file now.
Writing file data 1.
Numeric version of MyCallers[itemp].iaddr = 0
Numeric version of MyCallers[itemp].iaddr = 0
Numeric version of MyCallers[itemp].iaddr = 0
Numeric version of MyCallers[itemp].iaddr = 0
Reading Struct.txt:
Converted count: 4
Line read: '382206665
'
Line read: '9
'
Line read: '59233147
'
Line read: '8
'
Line read: '67372128
'
Line read: '7
'
Line read: '16830986
'
Line read: '10
'
0>201.2.200.22 - 22.200.2.201 ts:22.200.2.201 (9 times.)
1>123.211.135.3 - 3.135.211.123 ts:3.135.211.123 (8 times.)
2>96.4.4.4 - 4.4.4.96 ts:4.4.4.96 (7 times.)
3>10.210.0.1 - 1.0.210.10 ts:1.0.210.10 (10 times.)
To me, it looks like it's compiling and running fine.