Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| lehrkraefte:blc:informatik:ffprg2-2020:webdev [2021/01/08 07:58] – Ivo Blöchliger | lehrkraefte:blc:informatik:ffprg2-2020:webdev [2021/01/13 10:35] (current) – [Basic JavaScript] Ivo Blöchliger | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ===== Basic JavaScript ===== | ||
| + | Ein Crash-Course in 4 html-Dateien, | ||
| + | Bei Nachfrage oder konkreten Fragen liefere ich gerne mehr und konkrete Beispiele. | ||
| + | |||
| + | Une ein JavaScript-Spielerei von mir: https:// | ||
| + | |||
| + | |||
| + | ===== Einrichten ===== | ||
| + | * **Nur Windows**: Installation eines ssh-clients (z.B. [[https:// | ||
| + | * Passwort ändern: | ||
| + | * Sich per ssh verbinden, das Kommand '' | ||
| + | * (Mac, Linux, direkt auf der Konsole: ssh -p 40199 user.name@tech-lab.ch, | ||
| + | * 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 '' | ||
| + | * 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 '' | ||
| + | |||
| + | === Erste Webseite === | ||
| + | Text-Editor, | ||
| + | Erste html-Datei mit Namen index.html erstellen (und auf den Server laden) | ||
| + | <code html> | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | Text. | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | Ihre Seite sollte dann online unter https:// | ||
| + | |||
| + | Rousourcen für Web-Entwicklung: | ||
| + | * https:// | ||
| + | * https:// | ||
| + | * https:// | ||
| + | * 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:// | ||
| + | * OTA-Update-Möglichkeit (Over the air, d.h. direkt via Wireless, kein Gefummel mit Laptop und USB-Kabel unter dem Christbaum) | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | <code html index.html> | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | <meta name=" | ||
| + | <link rel=" | ||
| + | <link rel=" | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | |||
| + | function setProgram() { | ||
| + | var xhttp = new XMLHttpRequest(); | ||
| + | xhttp.onreadystatechange = function() { | ||
| + | if (this.readyState == 4 && this.status == 200) { | ||
| + | // Typical action to be performed when the document is ready: | ||
| + | | ||
| + | } | ||
| + | }; | ||
| + | var url = '/ | ||
| + | var sep = "?"; | ||
| + | for (const [key, value] of Object.entries(state)) { | ||
| + | url+=sep+key+" | ||
| + | sep="&"; | ||
| + | } | ||
| + | console.log(url); | ||
| + | xhttp.open(" | ||
| + | xhttp.send(); | ||
| + | } | ||
| + | |||
| + | state = { | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | }; | ||
| + | |||
| + | function mod(a,b) { | ||
| + | return a - Math.floor(a/ | ||
| + | } | ||
| + | |||
| + | function makeColor(img, | ||
| + | var h = (event.clientX-img.offsetLeft)/ | ||
| + | console.log(h); | ||
| + | var x = (1-Math.abs(mod(h*6, | ||
| + | rgb = [0,0,0]; | ||
| + | if (h<1/6) rgb = [1,x,0]; | ||
| + | else if (h<2/6) rgb = [x,1,0]; | ||
| + | else if (h<3/6) rgb = [0,1,x]; | ||
| + | else if (h<4/6) rgb = [0,x,1]; | ||
| + | else if (h<5/6) rgb = [x,0,1]; | ||
| + | else rgb = [1,0,x]; | ||
| + | v = Math.floor(rgb[2]*255)+256*(Math.floor(rgb[1]*255)+256*Math.floor(rgb[0]*255)); | ||
| + | s = v.toString(16); | ||
| + | while (s.length< | ||
| + | s = " | ||
| + | } | ||
| + | console.log(s); | ||
| + | state[name] = s; | ||
| + | document.getElementById(name).value = "#" | ||
| + | setProgram(); | ||
| + | } | ||
| + | |||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | | ||
| + | <label for=" | ||
| + | </ | ||
| + | < | ||
| + | | ||
| + | <label for=" | ||
| + | </ | ||
| + | <div> | ||
| + | <img src=" | ||
| + | </ | ||
| + | <div> | ||
| + | <img src=" | ||
| + | </ | ||
| + | <div> | ||
| + | <input type=" | ||
| + | | ||
| + | <label for=" | ||
| + | <input type=" | ||
| + | | ||
| + | <label for=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | </ | ||
| + | |||
| + | <code css style.css> | ||
| + | html { | ||
| + | font-family: | ||
| + | display: inline-block; | ||
| + | margin: 0px auto; | ||
| + | text-align: center; | ||
| + | background-color: | ||
| + | color: #aabbaa; | ||
| + | } | ||
| + | h1{ | ||
| + | color: #aaaaff; | ||
| + | padding: 2vh; | ||
| + | } | ||
| + | p{ | ||
| + | font-size: 1.5rem; | ||
| + | } | ||
| + | .button { | ||
| + | display: inline-block; | ||
| + | background-color: | ||
| + | border: none; | ||
| + | border-radius: | ||
| + | color: white; | ||
| + | padding: 10px 40px; | ||
| + | text-decoration: | ||
| + | font-size: 20px; | ||
| + | margin: -2px; | ||
| + | cursor: pointer; | ||
| + | } | ||
| + | .button2 { | ||
| + | background-color: | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | <code c++ xmastree.ino> | ||
| + | /********* | ||
| + | Rui Santos | ||
| + | Complete project details at https:// | ||
| + | https:// | ||
| + | |||
| + | Zusätzliche Libraries für diesen Sketch: | ||
| + | https:// | ||
| + | https:// | ||
| + | |||
| + | Entpacken, umbenennen (ohne -master) und nach ~/ | ||
| + | |||
| + | Zusätzliche Tools für diesen Sketch: | ||
| + | https:// | ||
| + | https:// | ||
| + | In den Ordner ~/ | ||
| + | | ||
| + | *********/ | ||
| + | |||
| + | // Import required libraries | ||
| + | #include " | ||
| + | #include " | ||
| + | #include " | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | |||
| + | // OTA | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | |||
| + | |||
| + | // Replace with your network credentials | ||
| + | const char* ssid = " | ||
| + | const char* password = " | ||
| + | const char* hostname = " | ||
| + | |||
| + | #include < | ||
| + | |||
| + | #define PIN 26 | ||
| + | #define NUMPIXEL 113 | ||
| + | |||
| + | Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXEL, | ||
| + | |||
| + | |||
| + | // 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 == " | ||
| + | return String(activeProgram); | ||
| + | } | ||
| + | if (var == " | ||
| + | return String(brightness); | ||
| + | } | ||
| + | if (var == " | ||
| + | return String(speed); | ||
| + | } | ||
| + | if (var == " | ||
| + | return String(activeProgram); | ||
| + | } | ||
| + | if (var == " | ||
| + | char buf[20]; | ||
| + | sprintf(buf, | ||
| + | return String(buf); | ||
| + | } | ||
| + | if (var == " | ||
| + | char buf[20]; | ||
| + | sprintf(buf, | ||
| + | return String(buf); | ||
| + | } | ||
| + | return String(); | ||
| + | } | ||
| + | |||
| + | |||
| + | void setup(){ | ||
| + | // Serial port for debugging purposes | ||
| + | Serial.begin(115200); | ||
| + | |||
| + | // Initialize SPIFFS | ||
| + | if(!SPIFFS.begin(true)){ | ||
| + | Serial.println(" | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | // Connect to Wi-Fi | ||
| + | WiFi.mode(WIFI_STA); | ||
| + | WiFi.begin(ssid, | ||
| + | Serial.print(" | ||
| + | Serial.println(ssid); | ||
| + | while (WiFi.waitForConnectResult() != WL_CONNECTED) { | ||
| + | Serial.println(" | ||
| + | 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 = " | ||
| + | else {// U_SPIFFS | ||
| + | type = " | ||
| + | SPIFFS.end(); | ||
| + | } | ||
| + | |||
| + | Serial.println(" | ||
| + | }) | ||
| + | .onEnd([]() { | ||
| + | Serial.println(" | ||
| + | }) | ||
| + | .onProgress([](unsigned int progress, unsigned int total) { | ||
| + | Serial.printf(" | ||
| + | }) | ||
| + | .onError([](ota_error_t error) { | ||
| + | Serial.printf(" | ||
| + | if (error == OTA_AUTH_ERROR) Serial.println(" | ||
| + | else if (error == OTA_BEGIN_ERROR) Serial.println(" | ||
| + | else if (error == OTA_CONNECT_ERROR) Serial.println(" | ||
| + | else if (error == OTA_RECEIVE_ERROR) Serial.println(" | ||
| + | else if (error == OTA_END_ERROR) Serial.println(" | ||
| + | }); | ||
| + | |||
| + | ArduinoOTA.begin(); | ||
| + | |||
| + | // Set up Hostname | ||
| + | if(!MDNS.begin(hostname)) { | ||
| + | | ||
| + | } else { | ||
| + | Serial.print(" | ||
| + | Serial.println(hostname); | ||
| + | // nicht sicher, ob die folgende Zeile nötig ist, macht aber Sinn... | ||
| + | // mdns_service_add(NULL, | ||
| + | MDNS.addService(" | ||
| + | } | ||
| + | |||
| + | // Route for root / web page | ||
| + | server.on("/", | ||
| + | request-> | ||
| + | }); | ||
| + | | ||
| + | // Route to load style.css file | ||
| + | server.on("/ | ||
| + | request-> | ||
| + | }); | ||
| + | |||
| + | // Route to load hsv400.png file | ||
| + | server.on("/ | ||
| + | request-> | ||
| + | }); | ||
| + | |||
| + | // Route to load favicon.ico file | ||
| + | server.on("/ | ||
| + | request-> | ||
| + | }); | ||
| + | |||
| + | // Route to set Programms | ||
| + | server.on("/ | ||
| + | String status = String(" | ||
| + | if(request-> | ||
| + | int b = atoi(request-> | ||
| + | b = (b<0 ? 0 : (b>255 ? 255 : b)); | ||
| + | if (b!=brightness) { | ||
| + | brightness = b; | ||
| + | pixels.setBrightness(brightness); | ||
| + | Serial.printf(" | ||
| + | status += " | ||
| + | status += brightness; | ||
| + | status += " "; | ||
| + | } | ||
| + | } | ||
| + | if(request-> | ||
| + | int s = atoi(request-> | ||
| + | s = (s<0 ? 0 : (s>255 ? 255 : s)); | ||
| + | if (s!=speed) { | ||
| + | speed = s; | ||
| + | Serial.printf(" | ||
| + | status+=" | ||
| + | status+=speed; | ||
| + | status+=" | ||
| + | } | ||
| + | } | ||
| + | if(request-> | ||
| + | int c1 = strtol(request-> | ||
| + | if (c1!=color1) { | ||
| + | color1=c1; | ||
| + | Serial.printf(" | ||
| + | char buf[20]; | ||
| + | sprintf(buf, | ||
| + | status+=" | ||
| + | status+=buf; | ||
| + | status+=" | ||
| + | } | ||
| + | } | ||
| + | if(request-> | ||
| + | int c2 = strtol(request-> | ||
| + | if (c2!=color2) { | ||
| + | color2=c2; | ||
| + | Serial.printf(" | ||
| + | char buf[20]; | ||
| + | sprintf(buf, | ||
| + | status+=" | ||
| + | status+=buf; | ||
| + | status+=" | ||
| + | } | ||
| + | } | ||
| + | if(request-> | ||
| + | int p = atoi(request-> | ||
| + | p = (p<0) ? 0 : (p> | ||
| + | if (p!=activeProgram) { | ||
| + | newProgram = p; | ||
| + | status += " program="; | ||
| + | status += newProgram; | ||
| + | } | ||
| + | } | ||
| + | request-> | ||
| + | }); | ||
| + | |||
| + | // Start server | ||
| + | server.begin(); | ||
| + | Serial.println(" | ||
| + | } | ||
| + | |||
| + | float fmap(float v, float fromMin, float fromMax, float toMin, float toMax) { | ||
| + | return (v-fromMin)*(toMax-toMin)/ | ||
| + | } | ||
| + | |||
| + | void cycleHSV(unsigned int & | ||
| + | float f = (speed> | ||
| + | if (counter> | ||
| + | counter = 0; | ||
| + | } | ||
| + | for (int i=0; i< | ||
| + | pixels.setPixelColor(i, | ||
| + | } | ||
| + | pixels.show(); | ||
| + | } | ||
| + | |||
| + | void stars(unsigned int & | ||
| + | float f = (speed> | ||
| + | if (counter> | ||
| + | counter = 0; | ||
| + | } | ||
| + | for (int i=0; i< | ||
| + | float v = 0.1*abs(10-abs(i%20 - counter*0.02*f)); | ||
| + | v = 4*v-3.0; | ||
| + | if (v<0) v=0.0; | ||
| + | /* if (i==0) { | ||
| + | Serial.printf(" | ||
| + | } */ | ||
| + | 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(" | ||
| + | } */ | ||
| + | pixels.setPixelColor(i, | ||
| + | } | ||
| + | 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<< | ||
| + | } | ||
| + | // | ||
| + | return r; | ||
| + | } | ||
| + | |||
| + | int scale(float f, int color) { | ||
| + | int r = 0; | ||
| + | for (int i=0; i<3; i++) { | ||
| + | r |= ((int)(f*(color & (0xff<< | ||
| + | } | ||
| + | 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< | ||
| + | pixels.setPixelColor(i, | ||
| + | } | ||
| + | } | ||
| + | |||
| + | if (start) { | ||
| + | start = false; | ||
| + | // Delay to connect to wifi will be random enough | ||
| + | randomSeed(micros()); | ||
| + | for (int i=0; i< | ||
| + | pos[i] = random(NUMPIXEL); | ||
| + | colors[i] = mix(random(10001)/ | ||
| + | // | ||
| + | count[i] = 0; | ||
| + | len[i] = (70+random(60))*(speed+20)/ | ||
| + | } | ||
| + | } else { | ||
| + | for (int i=0; i< | ||
| + | count[i]++; | ||
| + | float t = ((float)count[i])/ | ||
| + | t = t<0.5 ? 2.0*t : 2.0-2*t; | ||
| + | t = pow(t,4); | ||
| + | int c = scale(t, | ||
| + | /*if (i==0) { | ||
| + | Serial.printf(" | ||
| + | }*/ | ||
| + | pixels.setPixelColor(pos[i], | ||
| + | if (count[i]> | ||
| + | pos[i] = random(NUMPIXEL); | ||
| + | colors[i] = mix(random(10001)/ | ||
| + | count[i] = 0; | ||
| + | len[i] = (70+random(60))*(speed+20)/ | ||
| + | } | ||
| + | } | ||
| + | pixels.show(); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | void fade(unsigned int & | ||
| + | if (counter> | ||
| + | counter=0; | ||
| + | } | ||
| + | | ||
| + | float t = ((float)(counter))/ | ||
| + | t = cos(t*2*PI)/ | ||
| + | int c = mix(t); | ||
| + | for (int i=0; i< | ||
| + | pixels.setPixelColor(i, | ||
| + | } | ||
| + | pixels.show(); | ||
| + | } | ||
| + | |||
| + | unsigned int counter = 0; | ||
| + | unsigned long nextStep = millis(); | ||
| + | void loop() { | ||
| + | ArduinoOTA.handle(); | ||
| + | // init | ||
| + | if (newProgram!=activeProgram) { | ||
| + | activeProgram = newProgram; | ||
| + | nextStep = millis(); | ||
| + | counter = 0; | ||
| + | } | ||
| + | if (millis()> | ||
| + | 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++; | ||
| + | } | ||
| + | } | ||
| + | </ | ||