#include #include #include #include #include #include HardwareSerial uart(0); // WiFi credential // Use different ssid for both module to avoid confusion // example: // const char* ssid = "ESP32-LoRa-Chat1"; for user 1 // const char* ssid = "ESP32-LoRa-Chat2"; for user 2 const char* ssid = "ESP32-LoRa-Chat"; const char* password = "chatpass123"; WebServer server(80); #define MAX_MESSAGES 50 String messageBuffer[MAX_MESSAGES]; int messageCount = 0; const char index_html[] PROGMEM = R"rawliteral( ESP32 LoRa Chat
Connecting...
)rawliteral"; void LoRa_Join(){ uint32_t time = millis(); bool msg_done = true; uart.println("AT+MODE=LWOTAA"); delay(1000); while(1){ if(msg_done){ uart.println("AT+JOIN"); msg_done = false; } if(uart.available()){ String str = uart.readStringUntil('\n'); Serial.println(str); if(strcmp(str.c_str(), "+JOIN: Join failed\r") == 0){ msg_done = true; } if(strcmp(str.c_str(), "+JOIN: Done\r") == 0){ if(!msg_done){ break; } } } } } void LoRa_Send_MSG(char* msg){ uart.println(msg); while(1){ if(uart.available()){ String str = uart.readStringUntil('\n'); Serial.println(str); if(strcmp(str.c_str(), "+MSG: Done\r") == 0){ break; } } } } uint8_t lora_msg[32][51]; void LoRa_Send_MSGHEX(const char* msg){//parses string into multiple messages if needed //clear send buffer for(int i = 0; i < 32; i++){ for(int j = 0; j < 51; j++){ lora_msg[i][j] = 0; } } //get how many messages we will need (32 max = 1536 characters) int len = strlen(msg); int msg_no = len / 48; if((len % 48) != 0){ msg_no ++; } //prepare messages for(int i = 0; i < msg_no; i++){ if(len > 48){ lora_msg[i][0] = 51; lora_msg[i][1] = i+1; lora_msg[i][2] = msg_no; for(int j = 0; j < 48; j++){ lora_msg[i][3+j] = msg[j+i*48]; } len -= 48; } else{ lora_msg[i][0] = len+3; lora_msg[i][1] = i+1; lora_msg[i][2] = msg_no; for(int j = 0; j < len; j++){ lora_msg[i][3+j] = msg[j+i*48]; } len = 0; } } //send messages for(int i = 0; i < 32; i++){ if(lora_msg[i][0] != 0){ uart.print("AT+MSGHEX=\""); Serial.print("AT+MSGHEX=\""); for(int j = 0; j < lora_msg[i][0]; j++){ uart.printf("%02X",lora_msg[i][j]); Serial.printf("%02X",lora_msg[i][j]); } uart.println("\""); Serial.println("\""); } else{ return; } while(1){ if(uart.available()){ String str = uart.readStringUntil('\n'); Serial.println(str); if(strcmp(str.c_str(), "+MSGHEX: Done\r") == 0){ break; } } } } } int asciiToHex(char *asciiHexChar){ uint8_t hi, lo; uint8_t x; x = (asciiHexChar[0] & 0x4F); hi = (x & 0x0F) + ((x >> 6) * 9); x = (asciiHexChar[1] & 0x4F); lo = (x & 0x0F) + ((x >> 6) * 9); return (hi << 4) + lo; } int rx_buffer[32][51]; int rx_index = 0; void LoRa_Receive_MSG(){ if(uart.available()){ String str = uart.readStringUntil('\n'); Serial.println(str); if(str.indexOf("MSG: PORT: 1; RX:") > 0){ char rxBytes[3] = {0,0,0}; int rx_len = 51; for(int i = 0; i < rx_len; i++){ for(int j = 0; j < 2; j++){ rxBytes[j] = str.c_str()[i*2+j+20]; } rx_buffer[rx_index][i] = asciiToHex(rxBytes); if(i == 0){ rx_len = rx_buffer[rx_index][0]; } } if(rx_buffer[rx_index][1] == rx_buffer[rx_index][2]){ //transmit whole message rx_index = 0; String rxString = ""; for(int i = 0; i < 32; i++){ for(int j = 3; j < (rx_buffer[i][0]); j++){ rxString += (char)rx_buffer[i][j]; } if(rx_buffer[i][0] < 51){ break; } } addMessageToBuffer(rxString); } } } } void setup() { Serial.begin(115200); uart.begin(9600, SERIAL_8N1, RX, TX); if(!SPIFFS.begin(true)) { Serial.println("SPIFFS initialization failed!"); return; } Serial.println("Initializing LoRa..."); //add LoRa E5 module init here pinMode(5, OUTPUT); digitalWrite(5, LOW); delay(1000); digitalWrite(5, HIGH); delay(2000); LoRa_Join(); LoRa_Send_MSG("AT+MSG=\"hello\""); delay(1000); uart.println("AT+CLASS=C"); //LoRa E5 module init done WiFi.softAP(ssid, password); Serial.println("Access Point Started"); Serial.print("IP Address: "); Serial.println(WiFi.softAPIP()); server.on("/", HTTP_GET, handleRoot); server.on("/send", HTTP_POST, handleSendMessage); server.on("/messages", HTTP_GET, handleGetMessages); server.begin(); Serial.println("Web Server Started"); } void handleRoot() { server.send(200, "text/html", index_html); } void handleSendMessage() { if (server.hasArg("plain")) { StaticJsonDocument<200> doc; DeserializationError error = deserializeJson(doc, server.arg("plain")); if (!error) { String message = doc["message"].as(); String sender = doc["sender"].as(); Serial.println("Sending message"); Serial.print("Sender: "); Serial.println(sender); Serial.print("Message: "); Serial.println(message); String lora_msg = sender + ": " + message; LoRa_Send_MSGHEX(lora_msg.c_str()); addMessageToBuffer(sender + ": " + message); server.send(200, "application/json", "{\"status\":\"sent\"}"); } else { server.send(400, "application/json", "{\"error\":\"Invalid JSON\"}"); } } } void handleGetMessages() { StaticJsonDocument<2048> doc; JsonArray array = doc.createNestedArray("messages"); for(int i = 0; i < messageCount; i++) { array.add(messageBuffer[i]); } String response; serializeJson(doc, response); server.send(200, "application/json", response); } void addMessageToBuffer(String message) { if (messageCount >= MAX_MESSAGES) { for(int i = 0; i < MAX_MESSAGES - 1; i++) { messageBuffer[i] = messageBuffer[i + 1]; } messageCount--; } messageBuffer[messageCount++] = message; } String incoming = ""; int incomingByte = 0; void loop() { server.handleClient(); LoRa_Receive_MSG(); //if(uart.available()){ // String str = uart.readStringUntil('\n'); // Serial.println(str); // if(str.indexOf("MSG: PORT: 1; RX:") > 0){ // Serial.println("yayy"); // } //} //delay(1000); //if(Serial.available()){ // String str = Serial.readStringUntil('\n'); // uart.println(str); //} /* if (Serial.available() > 0) { incomingByte = Serial.read(); if(incomingByte != '#'){ incoming += (char)incomingByte; } if(incomingByte == '#'){ addMessageToBuffer(incoming); incoming = ""; } } */ /* int packetSize = LoRa.parsePacket(); if (packetSize) { byte recipient = LoRa.read(); byte sender = LoRa.read(); String incoming = ""; while (LoRa.available()) { incoming += (char)LoRa.read(); } if (recipient == localAddress) { addMessageToBuffer(incoming); } }*/ }