Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
lehrkraefte:blc:informatik:ffprg2-2020:webdev [2021/01/07 13:44] Ivo Blöchliger created |
lehrkraefte:blc:informatik:ffprg2-2020:webdev [2021/01/13 11:35] (current) Ivo Blöchliger [Basic JavaScript] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | === Einrichten === | + | ===== 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:// | * **Nur Windows**: Installation eines ssh-clients (z.B. [[https:// | ||
* Passwort ändern: | * Passwort ändern: | ||
Line 25: | Line 33: | ||
Ihre Seite sollte dann online unter https:// | 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++; | ||
+ | } | ||
+ | } | ||
+ | </ |