===== 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++;
}
}