===== Basic JavaScript ===== Ein Crash-Course in 4 html-Dateien, siehe https://ofi.tech-lab.ch/2021/teach/d0571f1e/javascript-basics/ Bei Nachfrage oder konkreten Fragen liefere ich gerne mehr und konkrete Beispiele. Une ein JavaScript-Spielerei von mir: https://glf.tech-lab.ch/teach/deadbeef/javascript/mancala/proto/mancala.html, oder ein Anfang von Tic-Tac-Toe, zum selber ausbauen: https://glf.tech-lab.ch/teach/deadbeef/javascript/tictactoe-generated/ ===== Einrichten ===== * **Nur Windows**: Installation eines ssh-clients (z.B. [[https://www.putty.org/|putty]]) * Passwort ändern: * Sich per ssh verbinden, das Kommand ''passwd'' eingeben und bestätigen (es wird bei der Eingabe der Passwörter gar nichts angezeigt). * (Mac, Linux, direkt auf der Konsole: ssh -p 40199 user.name@tech-lab.ch, Windows putty oder anderer SSH-client installieren (sollte jetzt auch native gehen, habe ich gehört)). * FileZilla installieren (auf Linux und Mac nicht nötig, aber möglich). * Datei index.html umbenennen, z.B. in start.html (enthält ihren Namen) * z.B. mit Filezilla oder auf der Konsole mit ''mv index.html start.html'' * Datei .htaccess umbennen oder löschen, damit Ihre Webseite von ausserhalb der KSBG erreichbar wird. Das kann via Konsole (ssh) oder mit Filezilla erfolgen. * z.B. mit Filezilla oder auf der Konsole mit ''mv .htaccess .htaccess.bak'' === Erste Webseite === Text-Editor, entweder lokal, oder direkt auf dem Server mit ''nano'' oder mit ''vim''. Erste html-Datei mit Namen index.html erstellen (und auf den Server laden)

Titel

Text.
Ihre Seite sollte dann online unter https://ofi.tech-lab.ch/2021/FF361/ in Ihrem Ordner sichtbar sein. Rousourcen für Web-Entwicklung: * https://wiki.selfhtml.org/ * https://www.w3schools.com/ * https://developer.mozilla.org/en-US/docs/Web * Und natürlich Google, Stackoverflow etc... * und ja, nur weil es in einem Browser läuft, heisst noch nicht, dass es in anderen Browsern auch läuft... Aber Explorer ist ja nicht mehr so sehr im Gebrauch. ====== Mein Christbaum hat ein Web-Interface ====== * ESP32 mit WS2812b LED-Streifen * Webserver auf dem ESP (erreichbar im meinem Heimnetzwerk unter http://baum/) * OTA-Update-Möglichkeit (Over the air, d.h. direkt via Wireless, kein Gefummel mit Laptop und USB-Kabel unter dem Christbaum) {{ :lehrkraefte:blc:informatik:ffprg2-2020:screenshot_20201224-105441.png?direct&200 |}} Xmas Tree Web Server

Xmas Tree Web Server

html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center; background-color: black; color: #aabbaa; } h1{ color: #aaaaff; padding: 2vh; } p{ font-size: 1.5rem; } .button { display: inline-block; background-color: #008CBA; border: none; border-radius: 4px; color: white; padding: 10px 40px; text-decoration: none; font-size: 20px; margin: -2px; cursor: pointer; } .button2 { background-color: #f44336; } /********* Rui Santos Complete project details at https://randomnerdtutorials.com https://randomnerdtutorials.com/esp32-web-server-spiffs-spi-flash-file-system/ Zusätzliche Libraries für diesen Sketch: https://github.com/me-no-dev/AsyncTCP/archive/master.zip https://github.com/me-no-dev/ESPAsyncWebServer/archive/master.zip Entpacken, umbenennen (ohne -master) und nach ~/Arduino/libraries/. speichern. Zusätzliche Tools für diesen Sketch: https://github.com/me-no-dev/arduino-esp32fs-plugin/releases/tag/1.0 https://github.com/me-no-dev/arduino-esp32fs-plugin/releases/download/1.0/ESP32FS-1.0.zip In den Ordner ~/Arudino/tools/. entpacken (den Ordner tools anlegen, falls nötig). *********/ // Import required libraries #include "WiFi.h" #include "ESPAsyncWebServer.h" #include "SPIFFS.h" #include #include // To set MAC-Adress (to avoid new MAC-Adresses every time). // OTA #include #include // Replace with your network credentials const char* ssid = "tech-lab"; const char* password = "rech-lab"; const char* hostname = "baum"; #include #define PIN 26 #define NUMPIXEL 113 Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXEL, PIN, NEO_GRB + NEO_KHZ800); // Create AsyncWebServer object on port 80 AsyncWebServer server(80); int activeProgram = 0; int newProgram = 2; int numPrograms = 4; int brightness = 255; int speed = 35; uint32_t color1 = 0xff0000; uint32_t color2 = 0x0000ff; // Replaces placeholder with LED state value String processor(const String& var){ Serial.println(var); if(var == "STATE"){ return String(activeProgram); } if (var == "BRIGHTNESS") { return String(brightness); } if (var == "SPEED") { return String(speed); } if (var == "NR") { return String(activeProgram); } if (var == "COLOR1") { char buf[20]; sprintf(buf, "%06x", color1); return String(buf); } if (var == "COLOR2") { char buf[20]; sprintf(buf, "%06x", color2); return String(buf); } return String(); } void setup(){ // Serial port for debugging purposes Serial.begin(115200); // Initialize SPIFFS if(!SPIFFS.begin(true)){ Serial.println("An Error has occurred while mounting SPIFFS"); return; } // Connect to Wi-Fi WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); Serial.print("Connecting to WiFi "); Serial.println(ssid); while (WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.println("Connection Failed! Rebooting..."); delay(2000); ESP.restart(); } // Print ESP32 Local IP Address Serial.println(WiFi.localIP()); ArduinoOTA.setPort(3232); ArduinoOTA.setHostname(hostname); ArduinoOTA .onStart([]() { String type; if (ArduinoOTA.getCommand() == U_FLASH) type = "sketch"; else {// U_SPIFFS type = "filesystem"; SPIFFS.end(); } Serial.println("Start updating " + type); }) .onEnd([]() { Serial.println("\nEnd"); }) .onProgress([](unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }) .onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); else if (error == OTA_END_ERROR) Serial.println("End Failed"); }); ArduinoOTA.begin(); // Set up Hostname if(!MDNS.begin(hostname)) { Serial.println("Error starting mDNS"); } else { Serial.print("MDNS started with name "); Serial.println(hostname); // nicht sicher, ob die folgende Zeile nötig ist, macht aber Sinn... // mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0); MDNS.addService("_http", "_tcp", 80); } // Route for root / web page server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(SPIFFS, "/index.html", String(), false, processor); }); // Route to load style.css file server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(SPIFFS, "/style.css", "text/css"); }); // Route to load hsv400.png file server.on("/hsv400.png", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(SPIFFS, "/hsv400.png", "image/png"); }); // Route to load favicon.ico file server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(SPIFFS, "/favicon.ico", "image/x-icon"); }); // Route to set Programms server.on("/prg", HTTP_GET, [](AsyncWebServerRequest *request){ String status = String("Status: "); if(request->hasParam("brightness")) { int b = atoi(request->getParam("brightness")->value().c_str()); b = (b<0 ? 0 : (b>255 ? 255 : b)); if (b!=brightness) { brightness = b; pixels.setBrightness(brightness); Serial.printf("Brightness=%d\n", brightness); status += "Brightness="; status += brightness; status += "   "; } } if(request->hasParam("speed")) { int s = atoi(request->getParam("speed")->value().c_str()); s = (s<0 ? 0 : (s>255 ? 255 : s)); if (s!=speed) { speed = s; Serial.printf("Speed=%d\n", speed); status+="speed="; status+=speed; status+="   "; } } if(request->hasParam("color1")) { int c1 = strtol(request->getParam("color1")->value().c_str(), NULL, 16); if (c1!=color1) { color1=c1; Serial.printf("Color1=%06x\n", color1); char buf[20]; sprintf(buf, "%06x", color1); status+="color1="; status+=buf; status+="   "; } } if(request->hasParam("color2")) { int c2 = strtol(request->getParam("color2")->value().c_str(), NULL, 16); if (c2!=color2) { color2=c2; Serial.printf("Color2=%06x\n", color2); char buf[20]; sprintf(buf, "%06x", color2); status+="color2="; status+=buf; status+="   "; } } if(request->hasParam("nr")) { int p = atoi(request->getParam("nr")->value().c_str()); p = (p<0) ? 0 : (p>=numPrograms ? numPrograms-1 : p); if (p!=activeProgram) { newProgram = p; status += " program="; status += newProgram; } } request->send(200, "text/plain", status); }); // Start server server.begin(); Serial.println("WebServer up and running!"); } float fmap(float v, float fromMin, float fromMax, float toMin, float toMax) { return (v-fromMin)*(toMax-toMin)/(fromMax-fromMin)+toMin; } void cycleHSV(unsigned int &counter) { float f = (speed>100) ? fmap(speed, 100,255,2,0.2) : fmap(speed, 0,100,10,2); if (counter>=f*NUMPIXEL) { counter = 0; } for (int i=0; i100) ? fmap(speed, 100,255, 1,10) : fmap(speed, 0,100, 0.2, 1); if (counter>=1000/f) { counter = 0; } for (int i=0; i v=%d\n", counter, v, (int)(v*v*255)); } */ v = pow(v,8); int r = (int)(v * ((color1 >> 16) & 255)); int g = (int)(v * ((color1 >> 8) & 255)); int b = (int)(v * (color1 & 255)); /* if (i==0 && r!=0) { Serial.printf("r=%d, g=%d, b=%d, color1=%06x, v=%f\n", r,g,b, color1, v); } */ pixels.setPixelColor(i, pixels.Color(r,g,b)); } pixels.show(); } int mix(float f) { int r = 0; for (int i=0; i<3; i++) { int c1 = color1 & (0xff << (8*i)); int c2 = color2 & (0xff << (8*i)); int c3 = (1.0-f)*c1+f*c2; r += c3 & (0xff<<(8*i)); } //Serial.printf("mix %f of color1=%06x and color2=%06x results in %06x\n", f, color1, color2, r); return r; } int scale(float f, int color) { int r = 0; for (int i=0; i<3; i++) { r |= ((int)(f*(color & (0xff<<(8*i))))) & (0xff<<(8*i)); } return r; } #define NUMFUNK 20 void funkeln(int counter) { static int pos[NUMFUNK]; static int colors[NUMFUNK]; static int count[NUMFUNK]; static int len[NUMFUNK]; static bool start=true; if (counter==0) { for (int i=0; i=len[i]) { pos[i] = random(NUMPIXEL); colors[i] = mix(random(10001)/10000.0); count[i] = 0; len[i] = (70+random(60))*(speed+20)/120.0; } } pixels.show(); } } void fade(unsigned int &counter) { if (counter>=speed*5+20) { counter=0; } float t = ((float)(counter))/(speed*5+20); t = cos(t*2*PI)/2+0.5; int c = mix(t); for (int i=0; inextStep) { switch(activeProgram) { case 0: cycleHSV(counter); nextStep += 40; // 25fps break; case 1: stars(counter); nextStep += 40; // 25fps break; case 2: funkeln(counter); nextStep += 40; // 25fps break; case 3: fade(counter); nextStep += 40; // 25fps break; } counter++; } }