Ciao
Io ho un Arduino Q 4gb ram e 32 storage, vorrei sapere come faccio ad avviare un sito(quindi che contiene html, Python e ino)senza App Lab, perché io dovrei portare io mio Arduino "in giro" solo che non ho un pc portatile e comunque sarebbe scomodo avviare sempre il programma con App Lab, vorrei sapere se ci sia un altro metodo che magari sia tipo che all'avviarsi dell'Arduino Q si avvii anche il sito.
Mi fate un favore se potete rispondere il prima possibile perché mi serve per fare un progetto scolastico.
Grazie per l'attenzione.
Codice:Ino
#include <Arduino_RouterBridge.h>
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
Bridge.begin();
// Il nome "set_led_state" deve essere uguale a quello in Python
Bridge.provide("set_led_state", set_led_state);
}
void loop() {
// Lascia vuoto o con piccoli task
}
void set_led_state(bool state) {
digitalWrite(13, state ? HIGH : LOW);
}
Codice:html
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Arduino Control - Enosh Edition</title>
<script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script>
<style>
:root {
--win-accent: #0078d4;
--sidebar-width: 260px;
--hover-bg: rgba(0, 0, 0, 0.04);
--active-bg: rgba(0, 120, 212, 0.08);
--win-card: rgba(255, 255, 255, 0.7); /* Card semi-trasparente */
}
body {
font-family: 'Segoe UI Variable Display', 'Segoe UI', sans-serif;
/* INTEGRATO: Sfondo gradiente dal primo codice */
background: linear-gradient(135deg, #dae2f8, #d6a4a4);
background-attachment: fixed;
margin: 0;
display: flex;
height: 100vh;
overflow: hidden;
}
/* --- SIDEBAR --- */
.sidebar {
width: var(--sidebar-width);
height: 100%;
background: rgba(255, 255, 255, 0.85); /* Leggera trasparenza sidebar */
backdrop-filter: blur(15px);
border-right: 1px solid rgba(0,0,0,0.1);
position: fixed;
left: -260px;
top: 0;
transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 1000;
padding: 10px;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.sidebar.open { left: 0; }
.sidebar-header {
font-weight: 600;
font-size: 15px;
margin-top: 50px;
margin-bottom: 25px;
padding-left: 15px;
color: #555;
letter-spacing: 0.5px;
}
.nav-item {
padding: 10px 15px;
border-radius: 6px;
margin-bottom: 4px;
cursor: pointer;
transition: all 0.2s ease;
font-size: 14px;
color: #444;
display: flex;
align-items: center;
gap: 12px;
position: relative;
}
.nav-item:hover { background: var(--hover-bg); }
.nav-item.active {
background: var(--active-bg);
color: var(--win-accent);
font-weight: 600;
}
/* --- CONTENUTO --- */
.main-content {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
}
.page { display: none; width: 100%; max-width: 400px; text-align: center; }
.page.active { display: block; animation: fadeIn 0.2s ease-out; }
@keyframes fadeIn {
from { opacity: 0; transform: scale(0.98); }
to { opacity: 1; transform: scale(1); }
}
/* INTEGRATO: Stile "Mica" per le card */
.win-card {
background: var(--win-card);
backdrop-filter: blur(20px) saturate(180%);
-webkit-backdrop-filter: blur(20px) saturate(180%);
padding: 40px;
border-radius: 12px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
border: 1px solid rgba(255, 255, 255, 0.3);
}
/* Bottone Menu */
.menu-btn {
position: fixed; top: 15px; left: 15px; z-index: 1100;
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(5px);
border: 1px solid #ddd; border-radius: 8px;
padding: 10px; cursor: pointer; display: flex; flex-direction: column; gap: 4px;
}
.menu-btn div { width: 18px; height: 2px; background: #333; }
input {
width: 100%; padding: 12px; margin: 10px 0; border-radius: 6px;
border: 1px solid rgba(0,0,0,0.1); box-sizing: border-box;
background: rgba(255, 255, 255, 0.5);
}
button#main-btn {
width: 100%; padding: 15px; border-radius: 8px; border: none;
background: var(--win-accent); color: white; cursor: pointer; font-weight: 600;
}
#btn-led { width: 100%; padding: 15px; border-radius: 8px; border: none; color: white; font-weight: 600; cursor: pointer; transition: 0.2s; }
.led-on { background: #d13438 !important; }
.led-off { background: #28a745 !important; }
#btn-led:hover { opacity: 0.9; transform: scale(1.02); }
.overlay {
display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background: rgba(0,0,0,0.2); z-index: 999;
}
.overlay.show { display: block; }
</style>
</head>
<body>
<div class="menu-btn" onclick="toggleSidebar()">
<div></div><div></div><div></div>
</div>
<div class="sidebar" id="sidebar">
<div class="sidebar-header">Gestione Sistema</div>
<div class="nav-item active" id="nav-control" onclick="switchPage('control')">
<span>🎮</span> Controllo manuale
</div>
<div class="nav-item" id="nav-ai" onclick="switchPage('ai')">
<span>🤖</span> AI-Mode
</div>
<div style="margin-top: auto; font-size: 11px; color: #666; padding-left: 15px;">ID: 374 | Enosh</div>
</div>
<div class="overlay" id="overlay" onclick="toggleSidebar()"></div>
<div class="main-content">
<div id="login-ui" class="win-card">
<h2>Accedi</h2>
<input type="text" id="user" placeholder="Enosh">
<input type="password" id="pass" placeholder="Password">
<button id="main-btn" onclick="checkLogin()">Accedi</button>
</div>
<div id="page-control" class="page">
<div class="win-card">
<h2>Manuale</h2>
<button id="btn-led" onclick="sendToggle()" class="led-off">ACCENDI</button>
<p id="status-text" style="font-size: 12px; margin-top: 15px; color: #444;">LED SPENTO</p>
</div>
</div>
<div id="page-ai" class="page">
<div class="win-card">
<h2>AI Mode</h2>
<p>Analisi sensori in corso...</p>
<div style="padding: 15px; background: rgba(0, 120, 212, 0.1); border-radius: 8px; color: #0078d4; font-weight: 500;">
Status: Ottimizzato
</div>
</div>
</div>
</div>
<script>
let socket;
function toggleSidebar() {
document.getElementById('sidebar').classList.toggle('open');
document.getElementById('overlay').classList.toggle('show');
}
function switchPage(pageId) {
document.querySelectorAll('.nav-item').forEach(el => el.classList.remove('active'));
document.querySelectorAll('.page').forEach(el => el.classList.remove('active'));
document.getElementById('nav-' + pageId).classList.add('active');
document.getElementById('page-' + pageId).classList.add('active');
toggleSidebar();
}
function checkLogin() {
if(document.getElementById('user').value === "Enosh" && document.getElementById('pass').value === "menosh2010") {
document.getElementById('login-ui').style.display = 'none';
document.getElementById('page-control').classList.add('active');
startSocket();
} else { alert("Dati errati!"); }
}
function startSocket() {
socket = io(`http://${window.location.host}`);
socket.on('led_status_update', (data) => {
const btn = document.getElementById('btn-led');
btn.textContent = data.led_is_on ? "SPEGNI" : "ACCENDI";
btn.className = data.led_is_on ? "led-on" : "led-off";
document.getElementById('status-text').textContent = data.status_text;
});
}
function sendToggle() { if(socket) socket.emit('toggle_led', {}); }
</script>
</body>
</html>
Codice: Python
from arduino.app_utils import *
from arduino.app_bricks.web_ui import WebUI
led_is_on = False
def get_led_status():
return {
"led_is_on": led_is_on,
"status_text": "LED ACCESO" if led_is_on else "LED SPENTO"
}
def toggle_led_state(client, data):
global led_is_on
led_is_on = not led_is_on
# Chiama Arduino
Bridge.call("set_led_state", led_is_on)
# Aggiorna tutti i client
ui.send_message('led_status_update', get_led_status())
def on_get_initial_state(client, data):
# Questa è la funzione che mancava nel log!
ui.send_message('led_status_update', get_led_status(), client)
ui = WebUI()
# Registriamo i nomi corretti dei messaggi
ui.on_message('toggle_led', toggle_led_state)
ui.on_message('get_initial_state', on_get_initial_state)
App.run()