Ajout partie Web
This commit is contained in:
BIN
data/Speed.jpg
Normal file
BIN
data/Speed.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
BIN
data/Speed.png
Normal file
BIN
data/Speed.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 110 KiB |
BIN
data/Speed.xcf
Normal file
BIN
data/Speed.xcf
Normal file
Binary file not shown.
@@ -13,10 +13,11 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Welcome!</h1>
|
||||
<h1>ESP8266 DCC Command Station</h1>
|
||||
<p>This is your ESP8266 DCC Command Station.</p>
|
||||
<p>Configure WiFi, manage XpressNet, and control your layout from here.</p>
|
||||
<p>For documentation, see <a href="/xpressnet.md">XpressNet Commands</a> and <a href="/README.md">Hardware Setup</a>.</p>
|
||||
<p>For documentation, see <a href="/xpressnet.html
|
||||
">XpressNet Commands</a> and <a href="/README.md">Hardware Setup</a>.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
53
data/mouse.html
Normal file
53
data/mouse.html
Normal file
@@ -0,0 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Mouse Speedometer</title>
|
||||
<style>
|
||||
body { background: #f4f4f4; font-family: Arial, sans-serif; }
|
||||
.container { max-width: 400px; margin: 40px auto; background: #fff; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); padding: 32px; }
|
||||
#speedometer { display: block; margin: 0 auto; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h2>Mouse Speedometer</h2>
|
||||
<div id="speedometer">
|
||||
<!-- Inline SVG for speedometer -->
|
||||
<svg width="300" height="200" viewBox="0 0 300 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<image href="Speed.png" x="0" y="0" width="300" height="200"/>
|
||||
<line id="needle" x1="150" y1="120" x2="150" y2="70" stroke="#e74c3c" stroke-width="6" stroke-linecap="round" />
|
||||
</svg>
|
||||
</div>
|
||||
<div style="text-align:center; margin-top:20px;">
|
||||
<button onclick="setSpeed(0)">0</button>
|
||||
<button onclick="setSpeed(100)">100</button>
|
||||
<button onclick="setSpeed(200)">200</button>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
/**
|
||||
* Speed is expected to be in the range 0-200. This function maps it to an angle for the needle.
|
||||
* at 100Kmh, needle is vertical, it's length is 50px, and it rotates from -120deg (0 speed) to +120deg (max speed).
|
||||
* At speed=100, x2=150, y2=70
|
||||
*/
|
||||
function setSpeed(speed)
|
||||
{
|
||||
// Clamp speed
|
||||
speed = Math.max(0, Math.min(200, speed));
|
||||
// Map speed to angle: 0 = -120deg, 100 = 0deg, 200 = +120deg
|
||||
var angle = -120 + (speed / 200) * 240;
|
||||
var rad = angle * Math.PI / 180;
|
||||
var r = 50; // needle length
|
||||
var cx = 150, cy = 120;
|
||||
var x2 = cx + r * Math.sin(rad); // Use sin for x, cos for y to match SVG coordinate system
|
||||
var y2 = cy - r * Math.cos(rad);
|
||||
document.getElementById('needle').setAttribute('x2', x2);
|
||||
document.getElementById('needle').setAttribute('y2', y2);
|
||||
}
|
||||
// Example: set speed to 0 initially
|
||||
setSpeed(20);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
20
data/speed.js
Normal file
20
data/speed.js
Normal file
@@ -0,0 +1,20 @@
|
||||
<script>
|
||||
// JavaScript to update needle and speed text
|
||||
function setSpeed(speed) {
|
||||
// Clamp speed
|
||||
speed = Math.max(0, Math.min(250, speed));
|
||||
// Map speed to angle: 0 = -120deg, 250 = +120deg
|
||||
var angle = -120 + (speed / 250) * 240;
|
||||
var rad = angle * Math.PI / 180;
|
||||
var r = 100; // needle length
|
||||
var cx = 150, cy = 150;
|
||||
var x2 = cx + r * Math.cos(rad);
|
||||
var y2 = cy + r * Math.sin(rad);
|
||||
document.getElementById('needle').setAttribute('x2', x2);
|
||||
document.getElementById('needle').setAttribute('y2', y2);
|
||||
document.getElementById('speedText').textContent = speed;
|
||||
}
|
||||
// Example: set speed to 120 after 1s
|
||||
setTimeout(function(){ setSpeed(120); }, 1000);
|
||||
// You can call setSpeed(value) from other JS code
|
||||
</script>
|
||||
6
data/speed.svg
Normal file
6
data/speed.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg width="500" height="405" xmlns="http://www.w3.org/2000/svg">
|
||||
<image href="speed.png" x="0" y="0" width="500" height="405"/>
|
||||
<!-- SVG needle overlay -->
|
||||
<line id="needle" x1="200" y1="200" x2="150" y2="50" stroke="#e74c3c" stroke-width="6"/>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 260 B |
39
data/speedometer-svgrepo-com.svg
Normal file
39
data/speedometer-svgrepo-com.svg
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 512.269 512.269" xml:space="preserve">
|
||||
<g>
|
||||
<!-- <line id="needle" x1="150" y1="150" x2="150" y2="50" stroke="#e74c3c" stroke-width="6" stroke-linecap="round" /> -->
|
||||
<path id="needle" d="M224.122,300.269c0,17.652,14.361,32.013,32.013,32.013c17.652,0,32.013-14.361,32.013-32.013c0-4.418-3.582-8-8-8
|
||||
s-8,3.582-8,8c0,8.83-7.183,16.013-16.013,16.013s-16.013-7.183-16.013-16.013c0-1.651,0.252-3.245,0.718-4.744
|
||||
c0.276-0.42,0.528-0.86,0.727-1.341c0.192-0.467,0.332-0.941,0.432-1.418c2.695-5.057,8.018-8.509,14.137-8.509
|
||||
c4.418,0,8-3.582,8-8s-3.582-8-8-8c-10.425,0-19.699,5.011-25.548,12.748l-121.92-50.265c-4.086-1.685-8.762,0.262-10.445,4.347
|
||||
c-1.684,4.085,0.262,8.761,4.347,10.445l121.875,50.247C224.236,297.246,224.122,298.744,224.122,300.269z"/>
|
||||
<path d="M437.249,119.155c-48.377-48.377-112.698-75.02-181.114-75.02c-68.417,0-132.737,26.643-181.115,75.02S0,231.853,0,300.269
|
||||
c0,50.1,14.519,98.672,41.986,140.467c1.537,2.338,4.089,3.607,6.693,3.607c1.508,0,3.032-0.426,4.386-1.315
|
||||
c3.692-2.427,4.718-7.387,2.292-11.079c-6.833-10.396-12.801-21.244-17.897-32.443l22.069-9.142
|
||||
c4.082-1.691,6.021-6.371,4.33-10.453c-1.691-4.083-6.372-6.019-10.453-4.33l-22.084,9.148
|
||||
c-9.168-24.361-14.316-50.139-15.185-76.461h23.88c4.418,0,8-3.582,8-8s-3.582-8-8-8H16.146
|
||||
c0.862-26.508,6.002-52.27,15.091-76.496l22.169,9.183c1.001,0.415,2.038,0.611,3.059,0.611c3.139,0,6.118-1.86,7.394-4.94
|
||||
c1.691-4.082-0.248-8.762-4.33-10.453l-22.169-9.183c10.703-23.558,25.285-45.409,43.42-64.763l16.88,16.88
|
||||
c1.562,1.562,3.609,2.343,5.657,2.343s4.095-0.781,5.657-2.343c3.125-3.124,3.125-8.189,0-11.313l-16.88-16.88
|
||||
c19.354-18.134,41.205-32.716,64.763-43.42l9.183,22.169c1.276,3.081,4.255,4.94,7.394,4.94c1.021,0,2.058-0.196,3.059-0.611
|
||||
c4.082-1.691,6.021-6.371,4.33-10.453l-9.183-22.169c24.226-9.089,49.988-14.229,76.496-15.091v23.871c0,4.418,3.582,8,8,8
|
||||
s8-3.582,8-8V60.281c26.508,0.862,52.27,6.002,76.496,15.091l-9.183,22.169c-1.691,4.082,0.248,8.762,4.33,10.453
|
||||
c1.001,0.415,2.038,0.611,3.059,0.611c3.139,0,6.118-1.86,7.394-4.94l9.183-22.169c23.558,10.703,45.409,25.285,64.762,43.42
|
||||
l-16.88,16.88c-3.125,3.124-3.125,8.189,0,11.313c1.562,1.562,3.609,2.343,5.657,2.343s4.095-0.781,5.657-2.343l16.88-16.88
|
||||
c18.134,19.354,32.716,41.205,43.42,64.763l-22.169,9.183c-4.082,1.691-6.021,6.371-4.33,10.453c1.276,3.081,4.255,4.94,7.394,4.94
|
||||
c1.021,0,2.058-0.196,3.059-0.611l22.169-9.183c9.089,24.226,14.229,49.988,15.091,76.496h-23.871c-4.418,0-8,3.582-8,8
|
||||
s3.582,8,8,8h23.879c-0.868,26.322-6.017,52.1-15.185,76.461l-22.084-9.148c-4.081-1.688-8.761,0.248-10.453,4.33
|
||||
c-1.691,4.082,0.248,8.762,4.33,10.453l22.069,9.142c-5.096,11.2-11.064,22.047-17.897,32.443c-2.427,3.692-1.4,8.652,2.292,11.079
|
||||
c3.691,2.425,8.652,1.4,11.079-2.292c27.468-41.794,41.986-90.367,41.986-140.467C512.269,231.853,485.626,167.532,437.249,119.155
|
||||
z"/>
|
||||
<path d="M328,388.135H184c-13.233,0-24,10.767-24,24v32c0,13.233,10.767,24,24,24h144c13.233,0,24-10.767,24-24v-32
|
||||
C352,398.901,341.233,388.135,328,388.135z M336,444.135c0,4.411-3.589,8-8,8H184c-4.411,0-8-3.589-8-8v-32c0-4.411,3.589-8,8-8
|
||||
h144c4.411,0,8,3.589,8,8V444.135z"/>
|
||||
<!-- <path d="M264,420.135h-16c-4.418,0-8,3.582-8,8s3.582,8,8,8h16c4.418,0,8-3.582,8-8S268.418,420.135,264,420.135z"/> -->
|
||||
<!-- <path d="M224,420.135h-16c-4.418,0-8,3.582-8,8s3.582,8,8,8h16c4.418,0,8-3.582,8-8S228.418,420.135,224,420.135z"/> -->
|
||||
<!-- <path d="M304,420.135h-16c-4.418,0-8,3.582-8,8s3.582,8,8,8h16c4.418,0,8-3.582,8-8S308.418,420.135,304,420.135z"/> -->
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
150
data/xpressnet.html
Normal file
150
data/xpressnet.html
Normal file
@@ -0,0 +1,150 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>XpressNet Command Reference</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; background: #f4f4f4; color: #333; margin: 0; padding: 0; }
|
||||
.container { max-width: 800px; margin: 40px auto; background: #fff; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); padding: 32px; }
|
||||
h1, h2, h3 { color: #0077cc; }
|
||||
table { width: 100%; border-collapse: collapse; margin-bottom: 24px; }
|
||||
th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }
|
||||
th { background: #e9e9e9; }
|
||||
pre { background: #f8f8f8; padding: 12px; border-radius: 4px; }
|
||||
a { color: #0077cc; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>XpressNet Command Reference</h1>
|
||||
<p>This page describes the available XpressNet commands and how to implement them in your command station firmware.</p>
|
||||
|
||||
<h2>XpressNet Command Table</h2>
|
||||
<table>
|
||||
<tr><th>Command Name</th><th>Code (Hex)</th><th>Description</th><th>Typical Usage</th></tr>
|
||||
<tr><td>Locomotive Speed</td><td>0xE4</td><td>Set speed and direction for a locomotive</td><td>Control train movement</td></tr>
|
||||
<tr><td>Function Group 1</td><td>0xE4</td><td>Control F0-F4 functions</td><td>Lights, sound, etc.</td></tr>
|
||||
<tr><td>Function Group 2</td><td>0xE4</td><td>Control F5-F8 functions</td><td>Extended functions</td></tr>
|
||||
<tr><td>Accessory Control</td><td>0x90</td><td>Switch turnouts, signals, etc.</td><td>Control layout accessories</td></tr>
|
||||
<tr><td>Read Feedback</td><td>0xF2</td><td>Query feedback modules</td><td>Detect occupancy, sensors</td></tr>
|
||||
<tr><td>Programming on Main</td><td>0xEF</td><td>Write CVs to decoders on main track</td><td>Decoder configuration</td></tr>
|
||||
<tr><td>Programming Track</td><td>0xED</td><td>Write/read CVs on programming track</td><td>Safe decoder programming</td></tr>
|
||||
<tr><td>Request Version</td><td>0x21</td><td>Request command station version</td><td>Handshake, diagnostics</td></tr>
|
||||
<tr><td>Emergency Stop</td><td>0x80</td><td>Stop all locomotives immediately</td><td>Safety/emergency</td></tr>
|
||||
</table>
|
||||
<p><em>Note: Actual codes and command structure may vary by implementation. Refer to the official XpressNet protocol documentation for full details.</em></p>
|
||||
|
||||
<h2>Implementing XpressNet in Your Command Station</h2>
|
||||
<ol>
|
||||
<li><b>Serial Communication:</b> XpressNet typically uses RS485 or TTL UART. Set up a serial interface at the required baud rate (commonly 62500 baud).</li>
|
||||
<li><b>Command Parsing:</b> In your firmware, implement a parser that reads incoming bytes and matches them to the command table above. Use a state machine to handle multi-byte commands.</li>
|
||||
<li><b>Command Handling:</b>
|
||||
<ul>
|
||||
<li>For each recognized command, implement a handler function (e.g., <code>handleLocomotiveSpeed()</code>, <code>handleAccessoryControl()</code>).</li>
|
||||
<li>Extract parameters (address, speed, function bits, etc.) from the command bytes.</li>
|
||||
<li>Update your internal state or send DCC packets as needed.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><b>Response Generation:</b> Some commands require a response (e.g., version request, feedback read). Format and send the appropriate reply bytes.</li>
|
||||
<li><b>Error Handling:</b> Implement checks for invalid or unsupported commands and respond with error codes if required by the protocol.</li>
|
||||
<li><b>Integration with DCC:</b> For commands that affect trains or accessories, translate XpressNet commands into DCC packets and send them to the track using your DCC output routines.</li>
|
||||
</ol>
|
||||
|
||||
<h3>Example: Handling a Locomotive Speed Command</h3>
|
||||
<pre><code>void handleLocomotiveSpeed(const uint8_t* data, size_t len) {
|
||||
// Parse address, speed, direction from data
|
||||
// Update DCC packet buffer
|
||||
// Send DCC packet to track
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<h3>References</h3>
|
||||
<ul>
|
||||
<li><a href="https://www.opendcc.de/elektronik/xpressnet/xpressnet_e.html">XpressNet Protocol Specification</a></li>
|
||||
<li><a href="https://www.nmra.org/index-nmra-standards-and-recommended-practices">DCC Protocol Overview</a></li>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Custom (DIY) XpressNet Extensions</h2>
|
||||
<p>You can add your own special commands to XpressNet by using unused command codes. Below are examples for switching mode and power control.</p>
|
||||
<table>
|
||||
<tr><th>Command Name</th><th>Code (Hex)</th><th>Payload Example</th><th>Description</th></tr>
|
||||
<tr><td>Switch Mode</td><td>0xF0</td><td>0x00</td><td>Switch to Analog mode</td></tr>
|
||||
<tr><td></td><td></td><td>0x01</td><td>Switch to DCC mode</td></tr>
|
||||
<tr><td></td><td></td><td>0x02</td><td>Switch to Marklin mode</td></tr>
|
||||
<tr><td>Power Track</td><td>0xF1</td><td>0x00</td><td>Power OFF</td></tr>
|
||||
<tr><td></td><td></td><td>0x01</td><td>Power ON</td></tr>
|
||||
</table>
|
||||
|
||||
<h3>Example Implementation in Firmware</h3>
|
||||
<pre><code>// Handle custom XpressNet commands
|
||||
void handleCustomXpressNet(const uint8_t* data, size_t len) {
|
||||
uint8_t cmd = data[0];
|
||||
switch (cmd) {
|
||||
case 0xF0: // Switch Mode
|
||||
if (len > 1) {
|
||||
uint8_t mode = data[1];
|
||||
switch (mode) {
|
||||
case 0x00: /* setAnalogMode(); */ break;
|
||||
case 0x01: /* setDCCMode(); */ break;
|
||||
case 0x02: /* setMarklinMode(); */ break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xF1: // Power Track
|
||||
if (len > 1) {
|
||||
if (data[1] == 0x01) {
|
||||
// powerOnTrack();
|
||||
} else {
|
||||
// powerOffTrack();
|
||||
}
|
||||
}
|
||||
break;
|
||||
// ... handle other custom commands ...
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>XpressNet over IP (WebSocket)</h2>
|
||||
<p>You can encapsulate XpressNet packets in WebSocket frames for remote control over IP. On the ESP8266, use a WebSocket server library (e.g., arduinoWebSockets).</p>
|
||||
|
||||
<h3>Basic Steps:</h3>
|
||||
<ol>
|
||||
<li>Start a WebSocket server on the ESP8266.</li>
|
||||
<li>On message received, treat the payload as an XpressNet packet and process it.</li>
|
||||
<li>Send any response packets back over WebSocket.</li>
|
||||
</ol>
|
||||
|
||||
<h3>Example (pseudo-code):</h3>
|
||||
<pre><code>#include <WebSocketsServer.h>
|
||||
WebSocketsServer webSocket = WebSocketsServer(81);
|
||||
|
||||
void onWebSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
|
||||
if (type == WStype_BIN) {
|
||||
// Process XpressNet packet
|
||||
handleXpressNet(payload, length);
|
||||
// Optionally send response:
|
||||
// webSocket.sendBIN(num, response, responseLen);
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
// ... WiFi setup ...
|
||||
webSocket.begin();
|
||||
webSocket.onEvent(onWebSocketEvent);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
webSocket.loop();
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<hr>
|
||||
<p>These extensions allow you to add custom features and remote control to your XpressNet command station.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -7,3 +7,4 @@ lib_deps =
|
||||
tzapu/WiFiManager
|
||||
Wire
|
||||
adafruit/Adafruit SSD1306
|
||||
board_build.filesystem = littlefs
|
||||
|
||||
100
src/main.cpp
100
src/main.cpp
@@ -5,6 +5,7 @@
|
||||
#include "WiFiManagerHelper.h"
|
||||
#include "main.h"
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <LittleFS.h>
|
||||
|
||||
#define SCREEN_WIDTH 128 // OLED display width, in pixels
|
||||
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
|
||||
@@ -23,34 +24,56 @@ Adafruit_SSD1306 *display;
|
||||
// Create web server instance on port 80
|
||||
ESP8266WebServer server(80);
|
||||
|
||||
// HTML content for welcome page
|
||||
const char* welcome_html = R"HTML(
|
||||
<!DOCTYPE html>
|
||||
<html lang=\"en\">
|
||||
<head>
|
||||
<meta charset=\"UTF-8\">
|
||||
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">
|
||||
<title>Welcome to ESP8266 DCC Command Station</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; background: #f4f4f4; color: #333; margin: 0; padding: 0; }
|
||||
.container { max-width: 600px; margin: 40px auto; background: #fff; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); padding: 32px; }
|
||||
h1 { color: #0077cc; }
|
||||
p { font-size: 1.2em; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class=\"container\">
|
||||
<h1>Welcome!</h1>
|
||||
<p>This is your ESP8266 DCC Command Station.</p>
|
||||
<p>Configure WiFi, manage XpressNet, and control your layout from here.</p>
|
||||
<p>For documentation, see <a href=\"/xpressnet.md\">XpressNet Commands</a> and <a href=\"/README.md\">Hardware Setup</a>.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
)HTML";
|
||||
// // HTML content for welcome page
|
||||
// const char* welcome_html = R"HTML(
|
||||
// <!DOCTYPE html>
|
||||
// <html lang=\"en\">
|
||||
// <head>
|
||||
// <meta charset=\"UTF-8\">
|
||||
// <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">
|
||||
// <title>Welcome to ESP8266 DCC Command Station</title>
|
||||
// <style>
|
||||
// body { font-family: Arial, sans-serif; background: #f4f4f4; color: #333; margin: 0; padding: 0; }
|
||||
// .container { max-width: 600px; margin: 40px auto; background: #fff; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); padding: 32px; }
|
||||
// h1 { color: #0077cc; }
|
||||
// p { font-size: 1.2em; }
|
||||
// </style>
|
||||
// </head>
|
||||
// <body>
|
||||
// <div class=\"container\">
|
||||
// <h1>Welcome!</h1>
|
||||
// <p>This is your ESP8266 DCC Command Station.</p>
|
||||
// <p>Configure WiFi, manage XpressNet, and control your layout from here.</p>
|
||||
// <p>For documentation, see <a href=\"/xpressnet.md\">XpressNet Commands</a> and <a href=\"/README.md\">Hardware Setup</a>.</p>
|
||||
// </div>
|
||||
// </body>
|
||||
// </html>
|
||||
// )HTML";
|
||||
|
||||
void handleWelcome() {
|
||||
server.send(200, "text/html", welcome_html);
|
||||
if (LittleFS.exists("/index.html")) {
|
||||
File file = LittleFS.open("/index.html", "r");
|
||||
if (file) {
|
||||
String html = file.readString();
|
||||
server.send(200, "text/html", html);
|
||||
file.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
server.send(404, "text/plain", "Welcome page not found");
|
||||
}
|
||||
|
||||
void handleXpressNetPage() {
|
||||
if (LittleFS.exists("/xpressnet.html")) {
|
||||
File file = LittleFS.open("/xpressnet.html", "r");
|
||||
if (file) {
|
||||
String html = file.readString();
|
||||
server.send(200, "text/html", html);
|
||||
file.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
server.send(404, "text/plain", "XpressNet page not found");
|
||||
}
|
||||
|
||||
void setup() {
|
||||
@@ -60,7 +83,32 @@ void setup() {
|
||||
displayInit();
|
||||
Serial.println("[DEBUG] OLED display initialized");
|
||||
setupWiFiManager();
|
||||
if (!LittleFS.begin()) {
|
||||
Serial.println("[ERROR] LittleFS mount failed");
|
||||
while(true) {
|
||||
display->clearDisplay();
|
||||
display->setTextSize(1);
|
||||
display->setTextColor(SSD1306_WHITE);
|
||||
display->setCursor(0, 0);
|
||||
display->println("LittleFS Mount Failed!");
|
||||
display->display();
|
||||
delay(1000);
|
||||
}
|
||||
} else {
|
||||
Serial.println("[DEBUG] LittleFS mounted");
|
||||
// List files in LittleFS root for debug
|
||||
// Serial.println("[DEBUG] LittleFS root directory:");
|
||||
// Dir dir = LittleFS.openDir("/");
|
||||
// while (dir.next()) {
|
||||
// Serial.print(" ");
|
||||
// Serial.print(dir.fileName());
|
||||
// Serial.print(" (size: ");
|
||||
// Serial.print(dir.fileSize());
|
||||
// Serial.println(")");
|
||||
// }
|
||||
}
|
||||
server.on("/", handleWelcome);
|
||||
server.on("/xpressnet.html", handleXpressNetPage);
|
||||
server.begin();
|
||||
Serial.println("[DEBUG] Web server started");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user