Ap начнется как в 5 минут после того, как код будет загружен, и я могу контакт с ним с моим телефоном, но после того, как я выключите свой телефон, AP выключится, и мне нужно для Ap Ap
IM, используя esp 32-c3, и я включил его с моего ПК-кабеля < /p>
Acces pocte < /p-ap ap ap ap ap ap ap ap ap ap ap ap ap ap ap ap ap ap ap ap ap ap ap ap ap ap> /> код: < /p>
#include
#include
#include
#include
// ======= WiFi AP =======
String ap_ssid = "Inventář_součástek";
String ap_pass = "12345678";
WebServer server(80);
// ======= HTML MENU =======
const char html_menu[] PROGMEM = R"rawliteral(
nav { background:#1e293b; display:flex; justify-content:center; flex-wrap:wrap; gap:10px; padding:10px; }
nav button { background:#3b82f6; color:#fff; border:none; padding:6px 12px; border-radius:6px; cursor:pointer; transition:0.2s; }
nav button:hover { background:#2563eb; }
)rawliteral";
// ======= HTML MAIN PAGE =======
const char html_main[] PROGMEM = R"rawliteral(
ESP Inventář a WiFi
:root {
--bg: #111827;
--text: #f1f5f9;
--nav-bg: #1e293b;
--nav-btn: #3b82f6;
--nav-btn-hover: #2563eb;
--btn-bg: #22d3ee;
--btn-text: #111827;
--btn-hover: #0891b2;
--btn-hover-text: #fff;
--table-border: #334155;
}
body { font-family: Arial,sans-serif; margin:0; padding:0; background:var(--bg); color:var(--text); }
nav { display:flex; justify-content:center; flex-wrap:wrap; gap:15px; padding:10px; background:var(--nav-bg); }
nav button { background:var(--nav-btn); color:#fff; border:none; padding:6px 12px; border-radius:6px; cursor:pointer; transition:0.2s; }
nav button:hover { background:var(--nav-btn-hover); }
.container { padding:20px; }
input,button,select { padding:8px; margin:4px 2px; border-radius:6px; border:none; font-size:16px; }
button { background:var(--btn-bg); color:var(--btn-text); cursor:pointer; transition:0.2s; }
button:hover { background:var(--btn-hover); color:var(--btn-hover-text); }
table { border-collapse:collapse; width:100%; margin-top:10px; table-layout:fixed; }
th,td { border:1px solid var(--table-border); padding:6px; text-align:left; word-wrap:break-word; font-size:14px; }
.qty-box { display:flex; gap:4px; align-items:center; justify-content:center; }
input[type=number] { width:60px; text-align:center; }
.form-row { display:flex; flex-wrap:wrap; gap:8px; margin-bottom:10px; }
.form-row input,.form-row button { flex:1 1 120px; min-width:80px; }
#search,#filterCat { width:100%; margin-bottom:10px; box-sizing:border-box; }
@media(max-width:600px){ th,td{font-size:12px;padding:4px;} input,button,select{font-size:14px;padding:6px;} .qty-box input[type=number]{width:40px;} }
.centered { display:flex; flex-direction:column; align-items:center; justify-content:center; min-height:80vh; text-align:center; }
%MENU%
Inventář součástek
Přidat
Všechny kategorie
#NázevKategorieMnožstvíPoznámkaAkce
Seznam ESP modulů
Ovládání PC
Zapnout PC
Vypnout PC
Světlo na stole
Zapnout
Vypnout
Ovládání světla
Zapnout
Vypnout
Aktuální teplota
Načítám…
Aktualizovat
Nastavení WiFi
Uložit a restartovat AP
Nastavení barev
Barva pozadí:
Barva textu:
Navigace:
Tlačítko:
Text tlačítka:
Ohraničení tabulky:
function showPage(id){
document.querySelectorAll('.page').forEach(p=>p.style.display='none');
document.getElementById(id).style.display='block';
}
// --------- Inventář ----------
let items=[];
async function loadItems(){ let r=await fetch('/load'); if(r.ok){ items=await r.json(); render(); } }
async function saveItems(){ await fetch('/save',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(items)}); }
function addItem(){ const n=document.getElementById('name').value.trim(); const c=document.getElementById('category').value.trim(); const q=parseInt(document.getElementById('qty').value)||0; const note=document.getElementById('note').value.trim(); if(!n) return; items.unshift({name:n,category:c,qty:q,note:note}); saveItems(); render(); document.getElementById('name').value=''; document.getElementById('category').value=''; document.getElementById('qty').value=1; document.getElementById('note').value=''; }
function deleteItem(i){ items.splice(i,1); saveItems(); render(); }
function updateQty(i,d){ items.qty=Math.max(0,items.qty+d); saveItems(); render(); }
function updateQtyInput(i,v){ items.qty=Math.max(0,parseInt(v)||0); saveItems(); render(); }
function updateCategoryFilter(){ const sel=document.getElementById('filterCat'); const cur=sel.value; let cats=[...new Set(items.map(it=>it.category).filter(c=>c))]; sel.innerHTML='Všechny kategorie'+cats.map(c=>`${c}`).join(''); }
function render(){ const t=document.getElementById('tbody'); const q=document.getElementById('search').value.toLowerCase().trim(); const cat=document.getElementById('filterCat').value; t.innerHTML=''; items.filter(it=>(it.name.toLowerCase().includes(q)||it.category.toLowerCase().includes(q)||it.note.toLowerCase().includes(q))&&(cat===''||it.category===cat)).forEach((it,i)=>{ t.innerHTML+=`${i+1}${it.name}${it.category}−+${it.note}
loadItems();
// --------- ESP ----------
let espModules=[{name:"ESP-01",status:"
function refreshESP(){ let ul=document.getElementById('espList'); ul.innerHTML=''; espModules.forEach(m=>{ let li=document.createElement('li'); li.textContent=m.name+" - "+m.status; ul.appendChild(li); }); }
// --------- TEMP ----------
async function updateTemp(){ let r=await fetch('/tempval'); if(r.ok){ let t=await r.text(); document.getElementById('tempVal').innerText=t+' °C'; } }
// --------- WiFi ----------
function updateWiFi(){
const ssid=document.getElementById('ssid').value;
const pass=document.getElementById('pass').value;
if(pass.length>0 && pass.lengthalert("AP aktualizováno!"));
}
// --------- THEME ----------
const defaultColors={"--bg":"#111827","--text":"#f1f5f9","--nav-bg":"#1e293b","--btn-bg":"#22d3ee","--btn-text":"#111827","--table-border":"#334155"};
function setColor(varName,value){ document.documentElement.style.setProperty(varName,value); }
async function saveTheme(){
const theme={bg:document.getElementById('bgColor').value,text:document.getElementById('textColor').value,nav:document.getElementById('navColor').value,btn:document.getElementById('btnColor').value,btnText:document.getElementById('btnTextColor').value,tableBorder:document.getElementById('tableBorder').value};
await fetch('/saveTheme',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(theme)});
alert('Barvy uloženy!');
}
async function resetColors(){
for(const k in defaultColors) setColor(k, defaultColors[k]);
const theme = {bg: defaultColors['--bg'], text: defaultColors['--text'], nav: defaultColors['--nav-bg'], btn: defaultColors['--btn-bg'], btnText: defaultColors['--btn-text'], tableBorder: defaultColors['--table-border']};
await fetch('/saveTheme',{method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(theme)});
document.getElementById('bgColor').value = theme.bg;
document.getElementById('textColor').value = theme.text;
document.getElementById('navColor').value = theme.nav;
document.getElementById('btnColor').value = theme.btn;
document.getElementById('btnTextColor').value = theme.btnText;
document.getElementById('tableBorder').value = theme.tableBorder;
alert('Barvy resetovány a uloženy!');
}
async function loadTheme(){ let r=await fetch('/loadTheme'); if(r.ok){ let t=await r.json(); setColor('--bg',t.bg||defaultColors['--bg']); setColor('--text',t.text||defaultColors['--text']); setColor('--nav-bg',t.nav||defaultColors['--nav-bg']); setColor('--btn-bg',t.btn||defaultColors['--btn-bg']); setColor('--btn-text',t.btnText||defaultColors['--btn-text']); setColor('--table-border',t.tableBorder||defaultColors['--table-border']); document.getElementById('bgColor').value=t.bg||defaultColors['--bg']; document.getElementById('textColor').value=t.text||defaultColors['--text']; document.getElementById('navColor').value=t.nav||defaultColors['--nav-bg']; document.getElementById('btnColor').value=t.btn||defaultColors['--btn-bg']; document.getElementById('btnTextColor').value=t.btnText||defaultColors['--btn-text']; document.getElementById('tableBorder').value=t.tableBorder||defaultColors['--table-border']; } }
loadTheme();
)rawliteral";
// ======= Helper =======
String withMenu(const char* page){
String out(page);
out.replace("%MENU%", String(FPSTR(html_menu)));
return out;
}
// ======= WiFi CONFIG SAVE/LOAD =======
void saveWiFiConfig() {
DynamicJsonDocument doc(256);
doc["ssid"] = ap_ssid;
doc["pass"] = ap_pass;
File f = LittleFS.open("/wifi.json", "w");
if (!f) { Serial.println("Chyba zápisu WiFi config"); return; }
serializeJson(doc, f);
f.close();
Serial.println("WiFi config uložen");
}
void loadWiFiConfig() {
if (!LittleFS.exists("/wifi.json")) return;
File f = LittleFS.open("/wifi.json","r");
if(!f){ Serial.println("Chyba čtení WiFi config"); return; }
DynamicJsonDocument doc(256);
DeserializationError err = deserializeJson(doc,f);
f.close();
if(err){ Serial.println("Chyba parsování WiFi config"); return; }
if (doc.containsKey("ssid")) ap_ssid = doc["ssid"].as();
if (doc.containsKey("pass")) ap_pass = doc["pass"].as();
Serial.println("WiFi config načten: " + ap_ssid);
}
// ======= Handlery =======
void handleRoot(){
server.sendHeader("Location","/main");
server.send(302, "text/plain", "");
}
void handleMain(){
String page = String(FPSTR(html_main));
page.replace("%SSID%", ap_ssid);
page.replace("%PASS%", ap_pass);
server.send(200,"text/html", withMenu(page.c_str()));
}
void handleLightOn(){ server.send(200,"text/plain","ON"); }
void handleLightOff(){ server.send(200,"text/plain","OFF"); }
void handleTempVal(){ float t=23.5; server.send(200,"text/plain",String(t)); }
// ======= Inventory =======
void handleLoad(){
if(!LittleFS.exists("/inventory.json")){ server.send(200,"application/json","[]"); return; }
File f=LittleFS.open("/inventory.json","r");
if(!f){ server.send(500,"text/plain","Chyba čtení"); return; }
String d=f.readString();
f.close();
server.send(200,"application/json",d);
}
void handleSave(){
// očekává JSON v těle požadavku (plain)
if(!server.hasArg("plain")){ server.send(400,"text/plain","Žádná data"); return; }
File f=LittleFS.open("/inventory.json","w");
if(!f){ server.send(500,"text/plain","Chyba zápisu"); return; }
f.print(server.arg("plain"));
f.close();
server.send(200,"text/plain","OK");
}
// ======= THEME =======
void handleSaveTheme(){
if(!server.hasArg("plain")){ server.send(400,"text/plain","Žádná data"); return; }
File f=LittleFS.open("/theme.json","w");
if(!f){ server.send(500,"text/plain","Chyba zápisu"); return; }
f.print(server.arg("plain"));
f.close();
server.send(200,"text/plain","OK");
}
void handleLoadTheme(){
if(!LittleFS.exists("/theme.json")){ server.send(200,"application/json","{}"); return; }
File f=LittleFS.open("/theme.json","r");
if(!f){ server.send(500,"text/plain","Chyba čtení"); return; }
String d=f.readString();
f.close();
server.send(200,"application/json",d);
}
// ======= WiFi UPDATE =======
void handleWiFiUpdate(){
if(server.hasArg("ssid")) ap_ssid = server.arg("ssid");
if(server.hasArg("pass")) ap_pass = server.arg("pass");
// restart AP se provede restartem modulu nebo opětovným voláním softAP
WiFi.softAP(ap_ssid.c_str(), ap_pass.c_str());
saveWiFiConfig();
server.send(200,"text/plain","AP updated");
Serial.println("AP updated via web: SSID=" + ap_ssid + " PASS=" + ap_pass);
}
// ======= Serial vstup (pro Update přes sérií) =======
void handleSerialInput(){
if(Serial.available()){
String line = Serial.readStringUntil('\n'); line.trim();
if(line.startsWith("SSID:")){
String newSSID = line.substring(5);
newSSID.trim();
if(newSSID.length()>=1){ ap_ssid = newSSID; WiFi.softAP(ap_ssid.c_str(), ap_pass.c_str()); saveWiFiConfig(); Serial.println("SSID updated to: " + ap_ssid); }
} else if(line.startsWith("PASS:")){
String newPass = line.substring(5);
newPass.trim();
if(newPass.length()>=8){ ap_pass = newPass; WiFi.softAP(ap_ssid.c_str(), ap_pass.c_str()); saveWiFiConfig(); Serial.println("Password updated"); }
}
}
}
// ======= Setup AP & server =======
void startAP(){
WiFi.mode(WIFI_AP);
WiFi.softAP(ap_ssid.c_str(), ap_pass.c_str());
Serial.println("");
Serial.println("===== WiFi AP =====");
Serial.print("SSID: "); Serial.println(ap_ssid);
Serial.print("Heslo: "); Serial.println(ap_pass);
Serial.println("
Serial.println("HTTP server běží.");
}
void setup() {
Serial.begin(115200);
delay(100);
if(!LittleFS.begin()){
Serial.println("Chyba při startu LittleFS");
// i když FS selže, pokračujeme, ale některé funkce nebudou fungovat
} else {
Serial.println("LittleFS inicializován");
}
loadWiFiConfig(); // načti uložené SSID a heslo (pokud jsou)
startAP();
// routy
server.on("/", handleRoot);
server.on("/main", handleMain);
server.on("/light/on", handleLightOn);
server.on("/light/off", handleLightOff);
server.on("/tempval", handleTempVal);
server.on("/load", handleLoad);
server.on("/save", HTTP_POST, handleSave);
server.on("/saveTheme", HTTP_POST, handleSaveTheme);
server.on("/loadTheme", handleLoadTheme);
server.on("/wifi_update", handleWiFiUpdate);
server.begin();
Serial.println("HTTP server spuštěn na portu 80");
}
// ======= Loop =======
void loop() {
server.handleClient();
handleSerialInput();
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... turning-of