Ajout partie Web

This commit is contained in:
2026-02-23 10:53:32 +01:00
parent b891c12400
commit c0d50a20ba
11 changed files with 346 additions and 28 deletions

BIN
data/Speed.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
data/Speed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

BIN
data/Speed.xcf Normal file

Binary file not shown.

23
data/index.html Normal file
View File

@@ -0,0 +1,23 @@
<!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>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.html
">XpressNet Commands</a> and <a href="/README.md">Hardware Setup</a>.</p>
</div>
</body>
</html>

53
data/mouse.html Normal file
View 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
View 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
View 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

View 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
View 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 &lt;WebSocketsServer.h&gt;
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>