This commit is contained in:
273
mock-server/debug_server/debug.css
Normal file
273
mock-server/debug_server/debug.css
Normal file
@@ -0,0 +1,273 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
background: #f5f5f5;
|
||||
color: #333;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
header {
|
||||
background: #2c3e50;
|
||||
color: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.status-bar {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.status-indicator {
|
||||
padding: 5px 10px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 4px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.status-indicator.connected {
|
||||
background: #27ae60;
|
||||
}
|
||||
|
||||
.status-indicator.disconnected {
|
||||
background: #e74c3c;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 2px solid #ddd;
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
padding: 12px 24px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-bottom: 3px solid transparent;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.tab-button:hover {
|
||||
color: #2c3e50;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.tab-button.active {
|
||||
color: #2c3e50;
|
||||
border-bottom-color: #3498db;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
display: none;
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.tab-content.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.section h2 {
|
||||
margin-bottom: 15px;
|
||||
color: #2c3e50;
|
||||
border-bottom: 2px solid #ecf0f1;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.section h3 {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 10px;
|
||||
color: #34495e;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: 500;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.form-group input,
|
||||
.form-group select,
|
||||
.form-group textarea {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.form-group textarea {
|
||||
resize: vertical;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #3498db;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: #2980b9;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: #95a5a6;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: #7f8c8d;
|
||||
}
|
||||
|
||||
.btn-small {
|
||||
padding: 5px 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.response-section {
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
background: #f8f9fa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.response-section pre {
|
||||
background: #2c3e50;
|
||||
color: #ecf0f1;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
overflow-x: auto;
|
||||
font-size: 13px;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.messages-section {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.messages-controls {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.messages-container {
|
||||
background: #2c3e50;
|
||||
color: #ecf0f1;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.message-item {
|
||||
padding: 8px;
|
||||
margin-bottom: 8px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 4px;
|
||||
border-left: 3px solid #3498db;
|
||||
}
|
||||
|
||||
.message-item .timestamp {
|
||||
color: #95a5a6;
|
||||
font-size: 11px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.message-item .topic {
|
||||
color: #3498db;
|
||||
font-weight: bold;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.message-item .payload {
|
||||
color: #ecf0f1;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
flex: 1;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
378
mock-server/debug_server/debug.js
Normal file
378
mock-server/debug_server/debug.js
Normal file
@@ -0,0 +1,378 @@
|
||||
// Configuration
|
||||
const API_BASE_URL = 'http://localhost:80';
|
||||
const MQTT_BROKER_URL = 'ws://localhost:9001/mqtt'; // WebSocket port for MQTT
|
||||
const WS_URL = 'http://localhost:80';
|
||||
|
||||
// State
|
||||
let mqttClient = null;
|
||||
let wsClient = null;
|
||||
let subscribedTopics = new Set();
|
||||
|
||||
// Initialize
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
|
||||
function init() {
|
||||
setupTabs();
|
||||
setupAPI();
|
||||
setupMQTT();
|
||||
setupWebSocket();
|
||||
setupDebug();
|
||||
setupQuickActions();
|
||||
}
|
||||
|
||||
// Tab Management
|
||||
function setupTabs() {
|
||||
const tabButtons = document.querySelectorAll('.tab-button');
|
||||
const tabContents = document.querySelectorAll('.tab-content');
|
||||
|
||||
tabButtons.forEach(button => {
|
||||
button.addEventListener('click', () => {
|
||||
const tabName = button.dataset.tab;
|
||||
|
||||
// Remove active class from all
|
||||
tabButtons.forEach(btn => btn.classList.remove('active'));
|
||||
tabContents.forEach(content => content.classList.remove('active'));
|
||||
|
||||
// Add active class to selected
|
||||
button.classList.add('active');
|
||||
document.getElementById(`${tabName}-tab`).classList.add('active');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// API Setup
|
||||
function setupAPI() {
|
||||
const endpointSelect = document.getElementById('api-endpoint');
|
||||
const paramsTextarea = document.getElementById('api-params');
|
||||
const sendBtn = document.getElementById('api-send-btn');
|
||||
const responsePre = document.getElementById('api-response');
|
||||
|
||||
sendBtn.addEventListener('click', async () => {
|
||||
const endpoint = endpointSelect.value;
|
||||
const [method, path] = endpoint.split(' ');
|
||||
const params = paramsTextarea.value.trim();
|
||||
|
||||
try {
|
||||
let options = {
|
||||
method: method,
|
||||
headers: {}
|
||||
};
|
||||
|
||||
if (method === 'POST' && params) {
|
||||
// Try to parse as JSON, otherwise use as form data
|
||||
try {
|
||||
const jsonData = JSON.parse(params);
|
||||
options.headers['Content-Type'] = 'application/json';
|
||||
options.body = JSON.stringify(jsonData);
|
||||
} catch {
|
||||
// Not JSON, use form data
|
||||
const formData = new URLSearchParams();
|
||||
const pairs = params.split('&');
|
||||
pairs.forEach(pair => {
|
||||
const [key, value] = pair.split('=');
|
||||
if (key && value) {
|
||||
formData.append(key, decodeURIComponent(value));
|
||||
}
|
||||
});
|
||||
options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
options.body = formData.toString();
|
||||
}
|
||||
}
|
||||
|
||||
const response = await fetch(`${API_BASE_URL}${path}`, options);
|
||||
const text = await response.text();
|
||||
|
||||
let formatted;
|
||||
try {
|
||||
formatted = JSON.stringify(JSON.parse(text), null, 2);
|
||||
} catch {
|
||||
formatted = text;
|
||||
}
|
||||
|
||||
responsePre.textContent = formatted;
|
||||
|
||||
} catch (error) {
|
||||
responsePre.textContent = `Error: ${error.message}`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// MQTT Setup
|
||||
function setupMQTT() {
|
||||
const topicInput = document.getElementById('mqtt-topic');
|
||||
const payloadTextarea = document.getElementById('mqtt-payload');
|
||||
const publishBtn = document.getElementById('mqtt-publish-btn');
|
||||
const subscribeBtn = document.getElementById('mqtt-subscribe-btn');
|
||||
const unsubscribeBtn = document.getElementById('mqtt-unsubscribe-btn');
|
||||
const subscribeTopicInput = document.getElementById('mqtt-subscribe-topic');
|
||||
const messagesContainer = document.getElementById('mqtt-messages');
|
||||
const clearMessagesBtn = document.getElementById('clear-messages-btn');
|
||||
|
||||
// Connect to MQTT broker
|
||||
try {
|
||||
mqttClient = mqtt.connect(MQTT_BROKER_URL, {
|
||||
clientId: 'debug-ui-' + Math.random().toString(16).substr(2, 8)
|
||||
});
|
||||
|
||||
mqttClient.on('connect', () => {
|
||||
console.log('MQTT connected');
|
||||
updateStatus('mqtt-status', 'MQTT: Connected', true);
|
||||
});
|
||||
|
||||
mqttClient.on('error', (error) => {
|
||||
console.error('MQTT error:', error);
|
||||
updateStatus('mqtt-status', 'MQTT: Error', false);
|
||||
});
|
||||
|
||||
mqttClient.on('close', () => {
|
||||
console.log('MQTT disconnected');
|
||||
updateStatus('mqtt-status', 'MQTT: Disconnected', false);
|
||||
});
|
||||
|
||||
mqttClient.on('message', (topic, message) => {
|
||||
addMessage(topic, message.toString());
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to connect to MQTT:', error);
|
||||
updateStatus('mqtt-status', 'MQTT: Connection Failed', false);
|
||||
}
|
||||
|
||||
publishBtn.addEventListener('click', () => {
|
||||
const topic = topicInput.value.trim();
|
||||
let payload = payloadTextarea.value.trim();
|
||||
|
||||
if (!topic) {
|
||||
alert('Please enter a topic');
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to parse as JSON, otherwise use as-is
|
||||
try {
|
||||
const jsonData = JSON.parse(payload);
|
||||
payload = JSON.stringify(jsonData);
|
||||
} catch {
|
||||
// Not JSON, use as-is
|
||||
}
|
||||
|
||||
if (mqttClient && mqttClient.connected) {
|
||||
mqttClient.publish(topic, payload, (err) => {
|
||||
if (err) {
|
||||
console.error('Publish error:', err);
|
||||
alert('Failed to publish: ' + err.message);
|
||||
} else {
|
||||
console.log('Published to', topic);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
alert('MQTT not connected');
|
||||
}
|
||||
});
|
||||
|
||||
subscribeBtn.addEventListener('click', () => {
|
||||
const topic = subscribeTopicInput.value.trim();
|
||||
if (!topic) {
|
||||
alert('Please enter a topic pattern');
|
||||
return;
|
||||
}
|
||||
|
||||
if (mqttClient && mqttClient.connected) {
|
||||
mqttClient.subscribe(topic, (err) => {
|
||||
if (err) {
|
||||
console.error('Subscribe error:', err);
|
||||
alert('Failed to subscribe: ' + err.message);
|
||||
} else {
|
||||
subscribedTopics.add(topic);
|
||||
console.log('Subscribed to', topic);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
alert('MQTT not connected');
|
||||
}
|
||||
});
|
||||
|
||||
unsubscribeBtn.addEventListener('click', () => {
|
||||
if (mqttClient && mqttClient.connected) {
|
||||
subscribedTopics.forEach(topic => {
|
||||
mqttClient.unsubscribe(topic);
|
||||
});
|
||||
subscribedTopics.clear();
|
||||
console.log('Unsubscribed from all topics');
|
||||
}
|
||||
});
|
||||
|
||||
clearMessagesBtn.addEventListener('click', () => {
|
||||
messagesContainer.innerHTML = '';
|
||||
});
|
||||
}
|
||||
|
||||
function addMessage(topic, payload) {
|
||||
const messagesContainer = document.getElementById('mqtt-messages');
|
||||
const messageDiv = document.createElement('div');
|
||||
messageDiv.className = 'message-item';
|
||||
|
||||
const timestamp = new Date().toLocaleTimeString();
|
||||
let formattedPayload = payload;
|
||||
try {
|
||||
formattedPayload = JSON.stringify(JSON.parse(payload), null, 2);
|
||||
} catch {}
|
||||
|
||||
messageDiv.innerHTML = `
|
||||
<div class="timestamp">${timestamp}</div>
|
||||
<div class="topic">${topic}</div>
|
||||
<div class="payload">${formattedPayload}</div>
|
||||
`;
|
||||
|
||||
messagesContainer.appendChild(messageDiv);
|
||||
|
||||
// Auto-scroll
|
||||
if (document.getElementById('auto-scroll').checked) {
|
||||
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// WebSocket Setup
|
||||
function setupWebSocket() {
|
||||
if (typeof io !== 'undefined') {
|
||||
try {
|
||||
wsClient = io(SOCKET_IO_URL);
|
||||
|
||||
wsClient.on('connect', () => {
|
||||
console.log('WebSocket connected');
|
||||
updateStatus('ws-status', 'WebSocket: Connected', true);
|
||||
});
|
||||
|
||||
wsClient.on('disconnect', () => {
|
||||
console.log('WebSocket disconnected');
|
||||
updateStatus('ws-status', 'WebSocket: Disconnected', false);
|
||||
});
|
||||
|
||||
wsClient.on('update', (data) => {
|
||||
console.log('WebSocket update:', data);
|
||||
// Could display in a separate section
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to connect WebSocket:', error);
|
||||
updateStatus('ws-status', 'WebSocket: Error', false);
|
||||
}
|
||||
} else {
|
||||
console.warn('Socket.io not loaded');
|
||||
updateStatus('ws-status', 'WebSocket: Library Not Loaded', false);
|
||||
}
|
||||
}
|
||||
|
||||
// Debug Endpoints Setup
|
||||
function setupDebug() {
|
||||
const debugButtons = document.querySelectorAll('[data-debug]');
|
||||
const responsePre = document.getElementById('debug-response');
|
||||
|
||||
debugButtons.forEach(button => {
|
||||
button.addEventListener('click', async () => {
|
||||
const action = button.dataset.debug;
|
||||
const endpoint = `/api/debug/${action}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(`${API_BASE_URL}${endpoint}`);
|
||||
const text = await response.text();
|
||||
responsePre.textContent = text;
|
||||
} catch (error) {
|
||||
responsePre.textContent = `Error: ${error.message}`;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Quick Actions Setup
|
||||
function setupQuickActions() {
|
||||
const quickActionButtons = document.querySelectorAll('[data-action]');
|
||||
|
||||
quickActionButtons.forEach(button => {
|
||||
button.addEventListener('click', () => {
|
||||
const action = button.dataset.action;
|
||||
const topicInput = document.getElementById('mqtt-topic');
|
||||
const payloadTextarea = document.getElementById('mqtt-payload');
|
||||
|
||||
switch (action) {
|
||||
case 'button-start1':
|
||||
topicInput.value = 'aquacross/button/00:00:00:00:00:01';
|
||||
payloadTextarea.value = JSON.stringify({
|
||||
type: 2,
|
||||
timestamp: Date.now()
|
||||
}, null, 2);
|
||||
break;
|
||||
case 'button-stop1':
|
||||
topicInput.value = 'aquacross/button/00:00:00:00:00:03';
|
||||
payloadTextarea.value = JSON.stringify({
|
||||
type: 1,
|
||||
timestamp: Date.now()
|
||||
}, null, 2);
|
||||
break;
|
||||
case 'button-start2':
|
||||
topicInput.value = 'aquacross/button/00:00:00:00:00:02';
|
||||
payloadTextarea.value = JSON.stringify({
|
||||
type: 2,
|
||||
timestamp: Date.now()
|
||||
}, null, 2);
|
||||
break;
|
||||
case 'button-stop2':
|
||||
topicInput.value = 'aquacross/button/00:00:00:00:00:04';
|
||||
payloadTextarea.value = JSON.stringify({
|
||||
type: 1,
|
||||
timestamp: Date.now()
|
||||
}, null, 2);
|
||||
break;
|
||||
case 'rfid-read':
|
||||
topicInput.value = 'aquacross/button/rfid/00:00:00:00:00:01';
|
||||
payloadTextarea.value = JSON.stringify({
|
||||
uid: 'TEST123456'
|
||||
}, null, 2);
|
||||
break;
|
||||
case 'battery-update':
|
||||
topicInput.value = 'aquacross/battery/00:00:00:00:00:01';
|
||||
payloadTextarea.value = JSON.stringify({
|
||||
voltage: 3600
|
||||
}, null, 2);
|
||||
break;
|
||||
case 'heartbeat':
|
||||
topicInput.value = 'heartbeat/alive/00:00:00:00:00:01';
|
||||
payloadTextarea.value = JSON.stringify({
|
||||
timestamp: Date.now()
|
||||
}, null, 2);
|
||||
break;
|
||||
case 'button-available':
|
||||
topicInput.value = 'aquacross/button/status/00:00:00:00:00:01';
|
||||
payloadTextarea.value = JSON.stringify({
|
||||
available: true,
|
||||
sleep: false,
|
||||
timestamp: Date.now()
|
||||
}, null, 2);
|
||||
break;
|
||||
case 'button-sleep':
|
||||
topicInput.value = 'aquacross/button/status/00:00:00:00:00:01';
|
||||
payloadTextarea.value = JSON.stringify({
|
||||
available: false,
|
||||
sleep: true,
|
||||
timestamp: Date.now()
|
||||
}, null, 2);
|
||||
break;
|
||||
}
|
||||
|
||||
// Auto-publish
|
||||
document.getElementById('mqtt-publish-btn').click();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Helper Functions
|
||||
function updateStatus(elementId, text, connected) {
|
||||
const element = document.getElementById(elementId);
|
||||
element.textContent = text;
|
||||
element.classList.remove('connected', 'disconnected');
|
||||
element.classList.add(connected ? 'connected' : 'disconnected');
|
||||
}
|
||||
|
||||
// Initialize on load
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
139
mock-server/debug_server/index.html
Normal file
139
mock-server/debug_server/index.html
Normal file
@@ -0,0 +1,139 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>AquaMaster Debug Server</title>
|
||||
<link rel="stylesheet" href="debug.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<h1>AquaMaster Debug Server</h1>
|
||||
<div class="status-bar">
|
||||
<span id="mqtt-status" class="status-indicator">MQTT: Disconnected</span>
|
||||
<span id="ws-status" class="status-indicator">WebSocket: Disconnected</span>
|
||||
<span id="api-status" class="status-indicator">API: Ready</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<nav class="tabs">
|
||||
<button class="tab-button active" data-tab="api">API Testing</button>
|
||||
<button class="tab-button" data-tab="mqtt">MQTT Testing</button>
|
||||
<button class="tab-button" data-tab="debug">Debug Endpoints</button>
|
||||
</nav>
|
||||
|
||||
<!-- API Testing Tab -->
|
||||
<div id="api-tab" class="tab-content active">
|
||||
<div class="section">
|
||||
<h2>API Endpoint Testing</h2>
|
||||
<div class="form-group">
|
||||
<label for="api-endpoint">Endpoint:</label>
|
||||
<select id="api-endpoint">
|
||||
<option value="GET /api/data">GET /api/data</option>
|
||||
<option value="POST /api/reset-best">POST /api/reset-best</option>
|
||||
<option value="POST /api/unlearn-button">POST /api/unlearn-button</option>
|
||||
<option value="POST /api/set-max-time">POST /api/set-max-time</option>
|
||||
<option value="GET /api/get-settings">GET /api/get-settings</option>
|
||||
<option value="POST /api/start-learning">POST /api/start-learning</option>
|
||||
<option value="POST /api/stop-learning">POST /api/stop-learning</option>
|
||||
<option value="GET /api/learn/status">GET /api/learn/status</option>
|
||||
<option value="GET /api/buttons/status">GET /api/buttons/status</option>
|
||||
<option value="GET /api/info">GET /api/info</option>
|
||||
<option value="POST /api/set-wifi">POST /api/set-wifi</option>
|
||||
<option value="GET /api/get-wifi">GET /api/get-wifi</option>
|
||||
<option value="POST /api/set-location">POST /api/set-location</option>
|
||||
<option value="GET /api/get-location">GET /api/get-location</option>
|
||||
<option value="GET /api/updateButtons">GET /api/updateButtons</option>
|
||||
<option value="POST /api/set-mode">POST /api/set-mode</option>
|
||||
<option value="GET /api/get-mode">GET /api/get-mode</option>
|
||||
<option value="POST /api/set-lane-config">POST /api/set-lane-config</option>
|
||||
<option value="GET /api/get-lane-config">GET /api/get-lane-config</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="api-params">Parameters (JSON or form data):</label>
|
||||
<textarea id="api-params" rows="4" placeholder='{"maxTime": 300, "maxTimeDisplay": 20}'></textarea>
|
||||
</div>
|
||||
<button id="api-send-btn" class="btn btn-primary">Send Request</button>
|
||||
<div class="response-section">
|
||||
<h3>Response:</h3>
|
||||
<pre id="api-response"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MQTT Testing Tab -->
|
||||
<div id="mqtt-tab" class="tab-content">
|
||||
<div class="section">
|
||||
<h2>MQTT Publish</h2>
|
||||
<div class="form-group">
|
||||
<label for="mqtt-topic">Topic:</label>
|
||||
<input type="text" id="mqtt-topic" placeholder="aquacross/button/00:00:00:00:00:01" value="aquacross/button/00:00:00:00:00:01">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mqtt-payload">Payload (JSON or text):</label>
|
||||
<textarea id="mqtt-payload" rows="4" placeholder='{"type": 2, "timestamp": 1234567890}'></textarea>
|
||||
</div>
|
||||
<button id="mqtt-publish-btn" class="btn btn-primary">Publish</button>
|
||||
|
||||
<div class="quick-actions">
|
||||
<h3>Quick Actions:</h3>
|
||||
<div class="button-group">
|
||||
<button class="btn btn-secondary" data-action="button-start1">Simulate Start1 Button</button>
|
||||
<button class="btn btn-secondary" data-action="button-stop1">Simulate Stop1 Button</button>
|
||||
<button class="btn btn-secondary" data-action="button-start2">Simulate Start2 Button</button>
|
||||
<button class="btn btn-secondary" data-action="button-stop2">Simulate Stop2 Button</button>
|
||||
<button class="btn btn-secondary" data-action="rfid-read">Simulate RFID Read</button>
|
||||
<button class="btn btn-secondary" data-action="battery-update">Simulate Battery Update</button>
|
||||
<button class="btn btn-secondary" data-action="heartbeat">Simulate Heartbeat</button>
|
||||
<button class="btn btn-secondary" data-action="button-available">Button Available (Wake)</button>
|
||||
<button class="btn btn-secondary" data-action="button-sleep">Button Sleep Mode</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>MQTT Subscribe</h2>
|
||||
<div class="form-group">
|
||||
<label for="mqtt-subscribe-topic">Topic Pattern:</label>
|
||||
<input type="text" id="mqtt-subscribe-topic" placeholder="# or aquacross/button/#" value="#">
|
||||
</div>
|
||||
<button id="mqtt-subscribe-btn" class="btn btn-primary">Subscribe</button>
|
||||
<button id="mqtt-unsubscribe-btn" class="btn btn-secondary">Unsubscribe All</button>
|
||||
|
||||
<div class="messages-section">
|
||||
<h3>Received Messages:</h3>
|
||||
<div class="messages-controls">
|
||||
<button id="clear-messages-btn" class="btn btn-small">Clear</button>
|
||||
<label><input type="checkbox" id="auto-scroll" checked> Auto-scroll</label>
|
||||
</div>
|
||||
<div id="mqtt-messages" class="messages-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Debug Endpoints Tab -->
|
||||
<div id="debug-tab" class="tab-content">
|
||||
<div class="section">
|
||||
<h2>Debug Endpoints</h2>
|
||||
<p>Direct access to debug endpoints for timer control:</p>
|
||||
<div class="button-group">
|
||||
<button class="btn btn-primary" data-debug="start1">Start Lane 1</button>
|
||||
<button class="btn btn-primary" data-debug="stop1">Stop Lane 1</button>
|
||||
<button class="btn btn-primary" data-debug="start2">Start Lane 2</button>
|
||||
<button class="btn btn-primary" data-debug="stop2">Stop Lane 2</button>
|
||||
</div>
|
||||
<div class="response-section">
|
||||
<h3>Last Response:</h3>
|
||||
<pre id="debug-response"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/mqtt@5/dist/mqtt.min.js"></script>
|
||||
<script src="https://cdn.socket.io/4.6.1/socket.io.min.js"></script>
|
||||
<script src="debug.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user