#include #include #include #include #include #include #include #include NeoPixelBus strip(16, 1); String clientssid = "Your_Network_Here"; String clientpass = "Dummy_Pass"; String cmdns = "led"; String apssid = "WLED-AP"; String appass = "wled1234"; int apchannel = 1; int aphide = 0; boolean useap = true; IPAddress staticip(0, 0, 0, 0); IPAddress staticgateway(0, 0, 0, 0); IPAddress staticsubnet(255, 255, 255, 0); byte col[]{255, 127, 0}; byte bri = 127; byte hue, sat; boolean ota_lock = false; boolean only_ap = false; int led_amount = 16; int nopwrled = 1; char HTTP_req[150]; ESP8266WebServer server(80); File fsUploadFile; void down() { bri = 0; setLeds(); Serial.println("MODULE TERMINATED"); while (1) {delay(1000);} } void reset() { bri = 0; setLeds(); Serial.println("MODULE RESET"); ESP.reset(); } void clearEEPROM() { for (int i = 0; i < 256; i++) { EEPROM.write(i, 0); } EEPROM.commit(); } void saveSettingsToEEPROM() { if (EEPROM.read(233) != 233) //set no first boot flag { clearEEPROM(); EEPROM.write(233, 233); } for (int i = 0; i < 32; ++i) { EEPROM.write(i, clientssid.charAt(i)); } for (int i = 32; i < 96; ++i) { EEPROM.write(i, clientpass.charAt(i-32)); } for (int i = 96; i < 128; ++i) { EEPROM.write(i, cmdns.charAt(i-96)); } for (int i = 128; i < 160; ++i) { EEPROM.write(i, apssid.charAt(i-128)); } for (int i = 160; i < 224; ++i) { EEPROM.write(i, appass.charAt(i-160)); } EEPROM.write(228, aphide); EEPROM.write(227, apchannel); EEPROM.write(229, led_amount); EEPROM.write(231, nopwrled); EEPROM.write(234, staticip[0]); EEPROM.write(235, staticip[1]); EEPROM.write(236, staticip[2]); EEPROM.write(237, staticip[3]); EEPROM.write(238, staticgateway[0]); EEPROM.write(239, staticgateway[1]); EEPROM.write(240, staticgateway[2]); EEPROM.write(241, staticgateway[3]); EEPROM.write(242, staticsubnet[0]); EEPROM.write(243, staticsubnet[1]); EEPROM.write(244, staticsubnet[2]); EEPROM.write(245, staticsubnet[3]); EEPROM.write(246, col[0]); EEPROM.write(247, col[1]); EEPROM.write(248, col[2]); EEPROM.write(249, bri); EEPROM.commit(); } void loadSettingsFromEEPROM() { if (EEPROM.read(233) != 233) //first boot/reset to default { saveSettingsToEEPROM(); return; } clientssid = ""; for (int i = 0; i < 32; ++i) { if (EEPROM.read(i) == 0) break; clientssid += char(EEPROM.read(i)); } clientpass = ""; for (int i = 32; i < 96; ++i) { if (EEPROM.read(i) == 0) break; clientpass += char(EEPROM.read(i)); } cmdns = ""; for (int i = 96; i < 128; ++i) { if (EEPROM.read(i) == 0) break; cmdns += char(EEPROM.read(i)); } apssid = ""; for (int i = 128; i < 160; ++i) { if (EEPROM.read(i) == 0) break; apssid += char(EEPROM.read(i)); } appass = ""; for (int i = 160; i < 224; ++i) { if (EEPROM.read(i) == 0) break; appass += char(EEPROM.read(i)); } aphide = EEPROM.read(228); if (aphide > 1) aphide = 1; apchannel = EEPROM.read(227); if (apchannel > 13 || apchannel < 1) apchannel = 1; led_amount = EEPROM.read(229); nopwrled = EEPROM.read(231); if (nopwrled > 1) nopwrled = 1; staticip[0] = EEPROM.read(234); staticip[1] = EEPROM.read(235); staticip[2] = EEPROM.read(236); staticip[3] = EEPROM.read(237); staticgateway[0] = EEPROM.read(238); staticgateway[1] = EEPROM.read(239); staticgateway[2] = EEPROM.read(240); staticgateway[3] = EEPROM.read(241); staticsubnet[0] = EEPROM.read(242); staticsubnet[1] = EEPROM.read(243); staticsubnet[2] = EEPROM.read(244); staticsubnet[3] = EEPROM.read(245); col[0] = EEPROM.read(246); col[1] = EEPROM.read(247); col[2] = EEPROM.read(248); bri = EEPROM.read(249); } void XML_response() { String resp; resp = resp + ""; resp = resp + ""; resp = resp + ""; resp = resp + bri; resp = resp + ""; for (int i = 0; i < 3; i++) { resp = resp + ""; resp = resp + col[i]; resp = resp + ""; } //enable toolbar here resp = resp + ""; server.send(200, "text/xml", resp); } void XML_response_settings() { Serial.println("XML settings response"); String resp; resp = resp + ""; resp = resp + ""; resp = resp + ""; resp = resp + clientssid; resp = resp + ""; resp = resp + ""; for (int i = 0; i < clientpass.length(); i++) { resp = resp + "*"; } resp = resp + ""; for (int i = 0; i < 4; i++) { resp = resp + ""; resp = resp + staticip[i]; resp = resp + ""; } for (int i = 0; i < 4; i++) { resp = resp + ""; resp = resp + staticgateway[i]; resp = resp + ""; } for (int i = 0; i < 4; i++) { resp = resp + ""; resp = resp + staticsubnet[i]; resp = resp + ""; } resp = resp + ""; resp = resp + cmdns; resp = resp + ""; resp = resp + ""; resp = resp + apssid; resp = resp + ""; resp = resp + ""; resp = resp + aphide; resp = resp + ""; resp = resp + ""; for (int i = 0; i < appass.length(); i++) { resp = resp + "*"; } resp = resp + ""; resp = resp + ""; resp = resp + apchannel; resp = resp + ""; resp = resp + ""; resp = resp + led_amount; resp = resp + ""; resp = resp + ""; resp = resp + nopwrled; resp = resp + ""; resp = resp + "0"; //NI resp = resp + "0"; //NI resp = resp + "0"; //NI resp = resp + ""; if (!WiFi.localIP()[0] == 0) { resp = resp + WiFi.localIP()[0]; resp = resp + "."; resp = resp + WiFi.localIP()[1]; resp = resp + "."; resp = resp + WiFi.localIP()[2]; resp = resp + "."; resp = resp + WiFi.localIP()[3]; } else { resp = resp + "Not connected"; } resp = resp + ""; resp = resp + ""; if (!WiFi.softAPIP()[0] == 0) { resp = resp + WiFi.softAPIP()[0]; resp = resp + "."; resp = resp + WiFi.softAPIP()[1]; resp = resp + "."; resp = resp + WiFi.softAPIP()[2]; resp = resp + "."; resp = resp + WiFi.softAPIP()[3]; } else { resp = resp + "Not active"; } resp = resp + ""; resp = resp + "Not implemented"; resp = resp + "WLED 0.2 OK"; resp = resp + ""; Serial.println(resp); server.send(200, "text/xml", resp); } char StrContains(char *str, char *sfind) { char found = 0; char index = 0; char len; len = strlen(str); if (strlen(sfind) > len) { return 0; } while (index < len) { if (str[index] == sfind[found]) { found++; if (strlen(sfind) == found) { return index; } } else { found = 0; } index++; } return 0; } uint8_t getNumberAfterStringPos(char str[], char spos) { String op; boolean no_n = false; int i = 0; while (!no_n) { if (str[spos + i + 1] > 47 && str[spos + i + 1] < 58) { op += str[spos + i + 1]; } else {no_n = true;} i++; } return op.toInt(); } void handleSettingsSet() { if (server.hasArg("CSSID")) clientssid = server.arg("CSSID"); if (server.hasArg("CPASS")) { if (!server.arg("CPASS").indexOf('*') == 0) { Serial.println("Setting pass"); clientpass = server.arg("CPASS"); } } if (server.hasArg("CMDNS")) cmdns = server.arg("CMDNS"); if (server.hasArg("APSSID")) apssid = server.arg("APSSID"); if (server.hasArg("APHSSID")) { aphide = 1; } else { aphide = 0; } if (server.hasArg("APPASS")) { if (!server.arg("APPASS").indexOf('*') == 0) appass = server.arg("APPASS"); } if (server.hasArg("APCHAN")) { int chan = server.arg("APCHAN").toInt(); if (chan > 0 && chan < 14) apchannel = chan; } if (server.hasArg("RESET")) //might be dangerous in case arg is always sent { clearEEPROM(); server.send(200, "text/plain", "Settings erased. Please wait for light to turn back on, then go to main page..."); reset(); } saveSettingsToEEPROM(); } boolean handleSet(String req) { Serial.println("handleSet:"); Serial.println(req); req.toCharArray(HTTP_req, 150, 0); if (!StrContains(HTTP_req, "ajax_in")) { if (StrContains(HTTP_req, "get-settings")) { XML_response_settings(); return true; } return false; } int pos = 0; pos = StrContains(HTTP_req, "A="); if (pos > 0) { bri = getNumberAfterStringPos(HTTP_req, pos); } pos = StrContains(HTTP_req, "R="); if (pos > 0) { col[0] = getNumberAfterStringPos(HTTP_req, pos); } pos = StrContains(HTTP_req, "G="); if (pos > 0) { col[1] = getNumberAfterStringPos(HTTP_req, pos); } pos = StrContains(HTTP_req, "B="); if (pos > 0) { col[2] = getNumberAfterStringPos(HTTP_req, pos); } Serial.println(col[0]); XML_response(); setLeds(); return true; } //format bytes String formatBytes(size_t bytes){ if (bytes < 1024){ return String(bytes)+"B"; } else if(bytes < (1024 * 1024)){ return String(bytes/1024.0)+"KB"; } else if(bytes < (1024 * 1024 * 1024)){ return String(bytes/1024.0/1024.0)+"MB"; } else { return String(bytes/1024.0/1024.0/1024.0)+"GB"; } } String getContentType(String filename){ if(server.hasArg("download")) return "application/octet-stream"; else if(filename.endsWith(".htm")) return "text/html"; else if(filename.endsWith(".html")) return "text/html"; else if(filename.endsWith(".css")) return "text/css"; else if(filename.endsWith(".js")) return "application/javascript"; else if(filename.endsWith(".png")) return "image/png"; else if(filename.endsWith(".gif")) return "image/gif"; else if(filename.endsWith(".jpg")) return "image/jpeg"; else if(filename.endsWith(".ico")) return "image/x-icon"; else if(filename.endsWith(".xml")) return "text/xml"; else if(filename.endsWith(".pdf")) return "application/x-pdf"; else if(filename.endsWith(".zip")) return "application/x-zip"; else if(filename.endsWith(".gz")) return "application/x-gzip"; return "text/plain"; } bool handleFileRead(String path){ Serial.println("handleFileRead: " + path); if(path.endsWith("/")) path += "index.htm"; String contentType = getContentType(path); String pathWithGz = path + ".gz"; if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){ if(SPIFFS.exists(pathWithGz)) path += ".gz"; File file = SPIFFS.open(path, "r"); size_t sent = server.streamFile(file, contentType); file.close(); return true; } return false; } void handleFileUpload(){ if(server.uri() != "/edit") return; HTTPUpload& upload = server.upload(); if(upload.status == UPLOAD_FILE_START){ String filename = upload.filename; if(!filename.startsWith("/")) filename = "/"+filename; Serial.print("handleFileUpload Name: "); Serial.println(filename); fsUploadFile = SPIFFS.open(filename, "w"); filename = String(); } else if(upload.status == UPLOAD_FILE_WRITE){ //Serial.print("handleFileUpload Data: "); Serial.println(upload.currentSize); if(fsUploadFile) fsUploadFile.write(upload.buf, upload.currentSize); } else if(upload.status == UPLOAD_FILE_END){ if(fsUploadFile) fsUploadFile.close(); Serial.print("handleFileUpload Size: "); Serial.println(upload.totalSize); } } void handleFileDelete(){ if(server.args() == 0) return server.send(500, "text/plain", "BAD ARGS"); String path = server.arg(0); Serial.println("handleFileDelete: " + path); if(path == "/") return server.send(500, "text/plain", "BAD PATH"); if(!SPIFFS.exists(path)) return server.send(404, "text/plain", "FileNotFound"); SPIFFS.remove(path); server.send(200, "text/plain", ""); path = String(); } void handleFileCreate(){ if(server.args() == 0) return server.send(500, "text/plain", "BAD ARGS"); String path = server.arg(0); Serial.println("handleFileCreate: " + path); if(path == "/") return server.send(500, "text/plain", "BAD PATH"); if(SPIFFS.exists(path)) return server.send(500, "text/plain", "FILE EXISTS"); File file = SPIFFS.open(path, "w"); if(file) file.close(); else return server.send(500, "text/plain", "CREATE FAILED"); server.send(200, "text/plain", ""); path = String(); } void handleFileList() { if(!server.hasArg("dir")) {server.send(500, "text/plain", "BAD ARGS"); return;} String path = server.arg("dir"); Serial.println("handleFileList: " + path); Dir dir = SPIFFS.openDir(path); path = String(); String output = "["; while(dir.next()){ File entry = dir.openFile("r"); if (output != "[") output += ','; bool isDir = false; output += "{\"type\":\""; output += (isDir)?"dir":"file"; output += "\",\"name\":\""; output += String(entry.name()).substring(1); output += "\"}"; entry.close(); } output += "]"; server.send(200, "text/json", output); } void setLeds() { double d = bri; double val = d /256; for (int i=0; i < led_amount; i++) { strip.SetPixelColor(i, RgbColor(col[0]*val, col[1]*val, col[2]*val)); } strip.Show(); } void setup() { Serial.begin(115200); Serial.println(); for(uint8_t t = 4; t > 0; t--) { Serial.printf("[SETUP] BOOT WAIT %d...\n", t); Serial.flush(); delay(1000); } SPIFFS.begin(); { Dir dir = SPIFFS.openDir("/"); while (dir.next()) { String fileName = dir.fileName(); size_t fileSize = dir.fileSize(); Serial.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str()); } Serial.printf("\n"); } Serial.println("Init EEPROM"); EEPROM.begin(256); loadSettingsFromEEPROM(); Serial.print("CC: SSID: "); Serial.print(clientssid); WiFi.disconnect(); //close old connections if (staticip[0] != 0) { WiFi.config(staticip, staticgateway, staticsubnet); } else { WiFi.config(0U, 0U, 0U); } if (apssid.length()>0) { Serial.print("USING AP"); Serial.println(apssid.length()); initAP(); } else { Serial.println("NO AP"); WiFi.softAPdisconnect(true); } initCon(); Serial.println(""); Serial.print("Connected! IP address: "); Serial.println(WiFi.localIP()); // Set up mDNS responder: if (cmdns != NULL && !only_ap && !MDNS.begin(cmdns.c_str())) { Serial.println("Error setting up MDNS responder!"); down(); } Serial.println("mDNS responder started"); //SERVER INIT //settings page server.on("/settings", HTTP_GET, [](){ if(!handleFileRead("/settings.htm")) server.send(404, "text/plain", "FileNotFound"); }); server.on("/button.png", HTTP_GET, [](){ if(!handleFileRead("/button.png")) server.send(404, "text/plain", "FileNotFound"); }); server.on("/favicon.ico", HTTP_GET, [](){ if(!handleFileRead("/favicon.ico")) server.send(404, "text/plain", "FileNotFound"); }); server.on("/", HTTP_GET, [](){ if(!handleFileRead("/index.htm")) server.send(404, "text/plain", "FileNotFound"); }); server.on("/reset", HTTP_GET, reset); server.on("/set-settings", HTTP_POST, [](){ handleSettingsSet(); server.send(200, "text/plain", "Settings saved. Please wait for light to turn back on, then go to main page..."); reset(); }); if (!ota_lock){ //load editor server.on("/edit", HTTP_GET, [](){ if(!handleFileRead("/edit.htm")) server.send(404, "text/plain", "FileNotFound"); }); //create file server.on("/edit", HTTP_PUT, handleFileCreate); //delete file server.on("/edit", HTTP_DELETE, handleFileDelete); //first callback is called after the request has ended with all parsed arguments //second callback handles file uploads at that location server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); }, handleFileUpload); //list directory server.on("/list", HTTP_GET, handleFileList); //kill module server.on("/down", HTTP_GET, down); //clear eeprom server.on("/cleareeprom", HTTP_GET, clearEEPROM); } //called when the url is not defined here, ajax-in; get-settings server.onNotFound([](){ if(!handleSet(server.uri())){ server.send(404, "text/plain", "FileNotFound"); } }); server.begin(); Serial.println("HTTP server started"); // Add service to MDNS MDNS.addService("http", "tcp", 80); // Initialize NeoPixel Strip strip.Begin(); setLeds(); /*if (nopwrled == 0) { pinMode(BUILTIN_LED, OUTPUT); }*/ } void loop() { server.handleClient(); } void initAP(){ WiFi.softAP(apssid.c_str(), appass.c_str(), apchannel, aphide); } void initCon() { int fail_count = 0; if (clientssid.length() <1) fail_count = 33; WiFi.begin(clientssid.c_str(), clientpass.c_str()); while(WiFi.status() != WL_CONNECTED) { delay(500); Serial.println("C_NC"); fail_count++; if (fail_count > 32) { WiFi.disconnect(); Serial.println("Can't connect to network. Opening AP..."); String save = apssid; only_ap = true; if (apssid.length() <1) apssid = "WLED-AP"; initAP(); apssid = save; return; } } }