#include #include #include #include #include // E32 LoRa Module Configuration #define M0_PIN 18 #define M1_PIN 19 #define AUX_PIN 21 #define SOFT_RX 16 #define SOFT_TX 17 // Default Access Point Settings const char* apSSID = "ESP32-LoRa-Gateway"; const char* apPassword = "config1234"; String wifiSSID = ""; String wifiPassword = ""; WebServer server(80); SoftwareSerial loraSerial(SOFT_RX, SOFT_TX); // RX, TX // System State Variables bool isTransmitting = false; bool isReceiving = false; int currentChannel = 1; int rssi = 0; unsigned long lastSignalTime = 0; #pragma pack(push, 1) typedef struct { uint8_t header[2]; // Packet header uint8_t length; // Data length uint8_t payload[32]; // Payload data uint8_t rssi; // Signal strength uint8_t checksum; // Checksum } LoRaPacket; #pragma pack(pop) void setup() { Serial.begin(115200); // Initialize EEPROM EEPROM.begin(512); // Initialize LoRa Module pinMode(M0_PIN, OUTPUT); pinMode(M1_PIN, OUTPUT); pinMode(AUX_PIN, INPUT); // Load WiFi credentials wifiSSID = EEPROM.readString(0); wifiPassword = EEPROM.readString(100); setLORAMode(3); // Configuration mode loraSerial.begin(9600); // Connect to WiFi or start AP if (wifiSSID != "") { WiFi.begin(wifiSSID.c_str(), wifiPassword.c_str()); Serial.println("Connecting to WiFi..."); int attempts = 0; while (WiFi.status() != WL_CONNECTED && attempts < 20) { delay(500); Serial.print("."); attempts++; } if (WiFi.status() == WL_CONNECTED) { Serial.println("\nWiFi Connected!"); Serial.print("IP Address: "); Serial.println(WiFi.localIP()); } else { WiFi.softAP(apSSID, apPassword); Serial.print("AP IP Address: "); Serial.println(WiFi.softAPIP()); } } else { WiFi.softAP(apSSID, apPassword); Serial.print("AP IP Address: "); Serial.println(WiFi.softAPIP()); } // Configure Web Server server.on("/", handleRoot); server.on("/transmitter", handleTransmitterPage); server.on("/receiver", handleReceiverPage); server.on("/wifi-config", handleWifiConfig); server.on("/set-wifi", HTTP_POST, handleSetWifi); server.on("/start-transmit", handleStartTransmit); server.on("/stop-transmit", handleStopTransmit); server.on("/set-channel", handleSetChannel); server.on("/get-status", handleGetStatus); server.onNotFound(handleNotFound); server.begin(); Serial.println("HTTP Server Started"); setLORAMode(0); // Normal operation mode } void loop() { server.handleClient(); // Receive data processing if (!isTransmitting) { String received = receiveLoRaData(); if (received != "") { Serial.print("Received: "); Serial.println(received); Serial.print("RSSI: "); Serial.println(rssi); } } } // Web Page Handlers void handleRoot() { String html = R"=====( ESP32 LoRa Gateway

ESP32 LoRa Gateway

System Status

Current Mode: )====="; html += isTransmitting ? "Transmitter Mode" : (isReceiving ? "Receiver Mode (Active)" : "Receiver Mode (Idle)"); html += R"=====(

Current Channel: )====="; html += currentChannel; html += R"=====(

Transmitter Mode Receiver Mode WiFi Configuration
)====="; server.send(200, "text/html", html); } void handleTransmitterPage() { String html = R"=====( Transmitter Mode

Transmitter Mode

Transmitter Controls

Status: )====="; html += isTransmitting ? "Transmitting..." : "Idle"; html += R"=====(

Back to Main )====="; server.send(200, "text/html", html); } void handleReceiverPage() { String html = R"=====( Receiver Mode

Receiver Mode

Receiver Status

Status: )====="; html += isReceiving ? "Signal Detected" : "No Signal"; html += R"=====(

Signal Strength: )====="; html += rssi; html += R"=====( dBm

Back to Main )====="; server.send(200, "text/html", html); } void handleWifiConfig() { String html = R"=====( WiFi Configuration

WiFi Configuration

Back to Main )====="; server.send(200, "text/html", html); } void handleSetWifi() { if (server.method() == HTTP_POST) { wifiSSID = server.arg("ssid"); wifiPassword = server.arg("password"); // Save to EEPROM EEPROM.writeString(0, wifiSSID); EEPROM.writeString(100, wifiPassword); EEPROM.commit(); String html = R"=====( Settings Saved

Settings Saved Successfully!

Please restart the device to apply WiFi changes.

Back to Main )====="; server.send(200, "text/html", html); } else { server.send(405, "text/plain", "Method Not Allowed"); } } void handleStartTransmit() { isTransmitting = true; String message = "TX_CH" + String(currentChannel) + "_" + String(millis()); // Send LoRa data LoRaPacket packet; packet.header[0] = 0xAA; packet.header[1] = 0x55; // FIXED: Correct min() usage with type casting int len = min((int)message.length(), 32); packet.length = len; memset(packet.payload, 0, 32); memcpy(packet.payload, message.c_str(), len); packet.checksum = 0; for (int i = 0; i < sizeof(packet) - 1; i++) { packet.checksum ^= ((uint8_t*)&packet)[i]; } loraSerial.write((uint8_t*)&packet, sizeof(packet)); server.send(200, "text/plain", "Transmission started: " + message); } void handleStopTransmit() { isTransmitting = false; server.send(200, "text/plain", "Transmission stopped"); } void handleSetChannel() { if (server.hasArg("ch")) { currentChannel = server.arg("ch").toInt(); // Set LoRa channel setLORAMode(3); // Configuration mode delay(100); uint8_t config[6]; config[0] = 0xC0; // HEAD config[1] = 0x00; // ADDH config[2] = 0x00; // ADDL uint8_t airDataRate = 2; // 2.4kbps uint8_t loraChannel = (currentChannel - 1) * 8; config[3] = (airDataRate << 5) | (loraChannel & 0x1F); config[4] = 0x44; // Subpacket/other options config[5] = 0x00; // CHAN loraSerial.write(config, 6); delay(100); setLORAMode(0); // Normal mode server.send(200, "text/plain", "Channel set to " + String(currentChannel)); } else { server.send(400, "text/plain", "Missing channel parameter"); } } void handleGetStatus() { String json = "{"; json += "\"receiving\":" + String(isReceiving ? "true" : "false") + ","; json += "\"rssi\":" + String(rssi); json += "}"; server.send(200, "application/json", json); } void handleNotFound() { server.send(404, "text/plain", "404: Not Found"); } // LoRa Module Functions void setLORAMode(uint8_t mode) { digitalWrite(M0_PIN, mode & 0x01 ? HIGH : LOW); digitalWrite(M1_PIN, mode & 0x02 ? HIGH : LOW); delay(100); } String receiveLoRaData() { static LoRaPacket packet; static int pos = 0; while (loraSerial.available()) { uint8_t b = loraSerial.read(); if (pos == 0 && b != 0xAA) continue; if (pos == 1 && b != 0x55) { pos = 0; continue; } ((uint8_t*)&packet)[pos] = b; pos++; if (pos >= sizeof(packet)) { pos = 0; uint8_t checksum = 0; for (int i = 0; i < sizeof(packet) - 1; i++) { checksum ^= ((uint8_t*)&packet)[i]; } if (checksum == packet.checksum) { rssi = packet.rssi - 256; lastSignalTime = millis(); isReceiving = true; return String((char*)packet.payload); } } } if (millis() - lastSignalTime > 1000) { isReceiving = false; } return ""; }