//SD #include //File System #include //SD Card Steuerung //GPS #include //Serielle Schnittstelle #include //GPS Daten verarbeiten //ESP #include // ESP-now Protokoll #include //WiFi //BT #include //Serial Protokoll für Bluetooth //Globals char tid[15] = {0}; //Transport ID int act_millis = 0; //Wie lange läuft die Station schon //GPS long gps_interval = 300000; static const int RX2Pin = 17, TX2Pin = 16; TinyGPSPlus gps; HardwareSerial gpsSerial(2); String gpsCoords = ""; String gpsDateTime = ""; //SD File myFile; //opened File File root; //root Folder //ESP const char* ssid = "XXX"; const char* password = "XXX"; uint8_t stationMac[] = {0x5C, 0xCF, 0x7F, 0x5, 0xFD, 0xF0}; //BT #if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED) #error Bluetooth is not enabled! Please run `make menuconfig` to and enable it #endif BluetoothSerial SerialBT; //Sensor struct SENSOR_DATA { float t; float temp; int door; }; String lastLine = "."; #define CHANNEL 1 void setup() { Serial.begin(9600); //normal Serial Serial.println("setup()"); initSDCard(); //SD Card init initGPS(); //GPS init initWiFi(); //ESP/WiFi init initBT(); //BT init } void loop() { if((act_millis + gps_interval) < millis()){ checkGPS(); act_millis = millis(); } //Test Serial Inputs if (Serial.available()) serialEvent(); } //init SD Card void initSDCard(){ Serial.println("initSDCard()"); if (!SD.begin(5)){ Serial.println("Card-Adapter mount Failed"); return; } else { Serial.println("SD Card-Adapter mounted"); } //check Card-Type uint8_t cardType = SD.cardType(); if (cardType == CARD_NONE) { Serial.println("No SD card attached"); return; } //if there is no File for the TransportId, create one if (!SD.exists("/tid.txt")){ myFile = SD.open("/tid.txt",FILE_WRITE); myFile.close(); } readTid(); //Show the fileSystem root = SD.open("/"); printDirectory(root, 0); root.close(); } //init GPS void initGPS(){ Serial.println("initGPS()"); gpsSerial.begin(9600, SERIAL_8N1, RX2Pin, TX2Pin); checkGPS(); } //init ESPNow void initESPNow(){ Serial.println("initESPNow()"); WiFi.disconnect(); if (esp_now_init() == ESP_OK){ Serial.println("ESPNow Init Success"); } else { Serial.println("ESPNow Init Failed"); ESP.restart(); } } //init WiFi void initWiFi(){ Serial.println("initWifi()"); esp_base_mac_addr_set(stationMac); Serial.println("ESP Now Config"); //Set device in AP mode to begin with WiFi.mode(WIFI_AP); // configure device AP mode configDeviceAP(); // This is the mac address of the Slave in AP Mode Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress()); // Init ESPNow with a fallback logic initESPNow(); // Once ESPNow is successfully Init, we will register for recv CB to // get recv packer info. esp_now_register_recv_cb(OnDataRecv); } //init Bluetooth void initBT(){ Serial.println("initBT()"); SerialBT.begin("Station"); //Device Name Serial.println("The BT device started, you can now pair with BT"); SerialBT.register_callback(btCallback); } //Callback: Test Serial Transport void serialEvent(){ Serial.print("serialEvent() "); while(Serial.available()){ char inChar = (char)Serial.read(); Serial.println(inChar); if (inChar != '\n' && inChar != '\r' && inChar != ' '){ switch (inChar){ case 'F': // send File => temp { Serial.println("F: send Temp File:"); //file to send: "/temp.log" myFile = SD.open("/temp.log"); if (myFile){ while(myFile.available()){ Serial.write(myFile.read()); } myFile.close(); Serial.println("F: End of File"); } else { Serial.println("E#Temperature File not found"); } break; } case 'D': // send File => door { Serial.println("D: send Door File"); //file to send: "/door.log" myFile = SD.open("/door.log"); if (myFile){ while(myFile.available()){ Serial.write(myFile.read()); } myFile.close(); Serial.println("D: End of File"); } else { Serial.println("E#Door File not found"); } break; } case 'L': // get last saved line { Serial.println("L#"+lastLine+">"); break; } case 'T': //set Transport ID { Serial.println("T: set Transport ID"); String newTid = ""; char ntid[15] = {0}; while(Serial.available()){ char t = (char)Serial.read(); if (t != '\n' && t != '\r') newTid += t; } myFile = SD.open("/tid.txt", FILE_WRITE); if (myFile){ myFile.println(newTid); myFile.close(); for (int i = 0; i < newTid.length(); i++){ ntid[i] = newTid.charAt(i); } for (int i = 0; i < 15; i++){ tid[i] = ntid[i]; } Serial.println("New Tid: "+String(tid)); } break; } case 'N': //create new Logfiles { Serial.println("N: create new Logfiles"); createNewLogFiles(); root = SD.open("/"); printDirectory(root, 0); root.close(); Serial.println("N#File Renamed"); break; } case 'S': //show File System { root = SD.open("/"); printDirectory(root, 0); root.close(); break; } default: { Serial.print("unidentified: "); Serial.println(inChar); break; } } } } } //Callback: Bluetooth Actions void btCallback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param){ Serial.println("btCallback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)"); if (event == ESP_SPP_SRV_OPEN_EVT){ Serial.println("BT Client Connected"); } else if (event == ESP_SPP_CLOSE_EVT){ Serial.println("BT Client Disconnected"); } else if (event == ESP_SPP_DATA_IND_EVT){ checkBTaction(); } } //Callback: Data Received from Master / ESPNow void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len){ Serial.println("OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len)"); char macStr[18]; snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); Serial.print("Last Packet received from: "); Serial.println(macStr); Serial.print("Last Packet received Data: "); Serial.println(*data); Serial.print("Last Packet Length: "); Serial.println(data_len); SENSOR_DATA tmp_s; memcpy(&tmp_s, data, sizeof(tmp_s)); Serial.print("t: "); Serial.println(tmp_s.t); Serial.print("temp: "); Serial.println(tmp_s.temp); Serial.print("door: "); Serial.println(tmp_s.door); //Save to file: *tid*_*sensortype*.log String sInfo; String dtype; String filename = ""; if (tmp_s.temp > 0) { filename="/temp.log"; dtype = "temp"; //Line: tid, macAddr, gpsDateTime, gpsCoords, tmp_s.type, tmp_s.temp, sInfo, millis lastLine = String(tid)+";"+macStr+";"+gpsDateTime+";"+gpsCoords+";"+dtype+";"+tmp_s.temp+";"+sInfo+";"+millis(); } else if (tmp_s.door > 0) { filename = "/door.log"; dtype = "door"; //Line: tid, macAddr, gpsDateTime, gpsCoords, tmp_s.type, tmp_s.temp, sInfo, millis lastLine = String(tid)+";"+macStr+";"+gpsDateTime+";"+gpsCoords+";"+dtype+";"+tmp_s.door+";"+sInfo+";"+millis(); } else filename = "unknown.log"; if (!SD.exists(filename)){ myFile = SD.open(filename, FILE_WRITE); myFile.close(); sInfo = '-'; } saveLastLine(filename); Serial.println("L#"+lastLine+">"); SerialBT.print("L#"+lastLine+">"); } //Service: check Data send via BT void checkBTaction(){ Serial.println("checkBTaction()"); if (SerialBT.available() > 0){ char btSingle = SerialBT.read(); Serial.println(btSingle); switch (btSingle){ case 'F': // send File => temp { Serial.println("BT/F: send Temp File:"); //file to send: "/temp.log" myFile = SD.open("/temp.log"); if (myFile){ while(myFile.available()){ //SerialBT.write(myFile.read()); String buffer = myFile.readStringUntil('\n'); //SerialBT.println(buffer); Serial.println(buffer); //SerialBT.flush(); } myFile.close(); Serial.println("BT/F: End of File"); } else { SerialBT.print("E#Temperature File not found"); } break; } case 'D': // send File => door { Serial.println("BT/D: send Door File"); //file to send: "/door.log" myFile = SD.open("/door.log"); if (myFile){ while(myFile.available()){ SerialBT.write(myFile.read()); } myFile.close(); Serial.println("BT/D: End of File"); } else { SerialBT.print("E#Door File not found"); } break; } case 'L': // get last saved line { Serial.println("BT/L: send lastLine"); SerialBT.print("L#"+String(lastLine)+">"); break; } case 'T': //set Transport ID { Serial.println("BT/T: set Transport ID"); String newTid = ""; char ntid[15] = {0}; while(SerialBT.available()){ char t = (char)SerialBT.read(); if (t != '\n' && t != '\r') newTid += t; } if (newTid != ""){ myFile = SD.open("/tid.txt", FILE_WRITE); if (myFile){ myFile.println(newTid); myFile.close(); for (int i = 0; i < newTid.length(); i++){ ntid[i] = newTid.charAt(i); } for (int i = 0; i < 15; i++){ tid[i] = ntid[i]; } Serial.println("BT/New Tid: "+String(tid)); } } SerialBT.print("T#"+String(tid)); break; } case 'N': //create new Logfiles { Serial.println("BT/N: create new Logfiles"); createNewLogFiles(); SerialBT.print("I#Files Renamed"); break; } case 'S': //show File System { root = SD.open("/"); printDirectory(root, 0); root.close(); break; } default: { Serial.print("BT: unidentified "); Serial.println(btSingle); while(SerialBT.available()){ char t = (char)SerialBT.read(); Serial.print(t); } break; } } } } //Service: create New Logfiles void createNewLogFiles(){ String newNameTemp = "/"+String(millis())+"_temp.log"; String oldNameTemp = "/temp.log"; renameFile(SD,oldNameTemp.c_str(),newNameTemp.c_str()); myFile = SD.open(oldNameTemp,FILE_WRITE); myFile.close(); String newNameDoor = "/"+String(millis())+"_door.log"; String oldNameDoor = "/door.log"; renameFile(SD,oldNameDoor.c_str(),newNameDoor.c_str()); myFile = SD.open(oldNameDoor,FILE_WRITE); myFile.close(); } //Service: Save Last SensorLine void saveLastLine(String filename){ Serial.println("saveLastLine(String type)"); myFile = SD.open(filename, FILE_APPEND); Serial.println("Trying to save to "+String(filename)); if (myFile){ myFile.print(lastLine); myFile.println(); myFile.close(); Serial.println("Data saved to File "+String(filename)); } else { Serial.println("!!! File not written. Lost: "+String(lastLine)); } //root = SD.open("/"); //printDirectory(root,0); //root.close(); } //Service: config AD SSID void configDeviceAP(){ Serial.println("configDeviceAP()"); bool result = WiFi.softAP(ssid, password, CHANNEL, 0); if (!result){ Serial.println("AP Config failed"); } else { Serial.println("AP Config Success. Broadcasting with AP: "+String(ssid)); } } //Service: check GPS Data void checkGPS(){ Serial.println("checkGPS()"); while(gpsSerial.available() > 0){ if (gps.encode(gpsSerial.read())){ serialGPSData(); } } if (millis() > 5000 && gps.charsProcessed() < 10){ Serial.println(F("no GPS-Module detected: check wiring!")); } } //Service: read Serial GPS Data void serialGPSData(){ Serial.println("serialGPSData()"); gpsDateTime = ""; gpsCoords = ""; Serial.print(("Location: ")); if (gps.location.isValid()){ gpsCoords = String(gps.location.lat(),6)+", "+String(gps.location.lng(),6); } else { gpsCoords = String("Kein ausreichendes GPS Signal"); } Serial.print(" "+gpsCoords+" "); Serial.print("Date/Time: "); if (gps.date.isValid()){ if (gps.time.hour()+1 < 10) gpsDateTime += "0"; gpsDateTime += String(gps.time.hour()+1); gpsDateTime += ":"; if (gps.time.minute() < 10) gpsDateTime += "0"; gpsDateTime += String(gps.time.minute()); gpsDateTime += ":"; if (gps.time.second() < 10) gpsDateTime += "0"; gpsDateTime += String(gps.time.second()); } else { gpsDateTime += "Millis: "; gpsDateTime += String(millis()); } Serial.print(gpsDateTime); Serial.println(); } //Service: read TransportID void readTid(){ Serial.println("readTid()"); //read saved TransportId myFile = SD.open("/tid.txt"); //if the file exists if (myFile){ Serial.print("Reading TransportId ... "); //read from file, until there is nothing else in it: int counter = 0; while (myFile.available()){ char ltr = myFile.read(); //no linebreaks allowed if (ltr != '\n'){ tid[counter] = ltr; } counter ++; } Serial.println(tid); myFile.close(); } else { //if the file won't open, print an error: Serial.println("wasn't able to open: tid.txt"); } } //Service: print Directory void printDirectory(File dir, int numTabs){ Serial.println("printDirectory(File dir, int numTabs)"); while (true){ File entry = dir.openNextFile(); if (!entry){ break; //no more files } for (uint8_t i = 0; i