-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
11da34d
commit 6a5a251
Showing
23 changed files
with
657 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.pio | ||
.vscode/.browse.c_cpp.db* | ||
.vscode/c_cpp_properties.json | ||
.vscode/launch.json | ||
.vscode/ipch |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
// See http://go.microsoft.com/fwlink/?LinkId=827846 | ||
// for the documentation about the extensions.json format | ||
"recommendations": [ | ||
"platformio.platformio-ide" | ||
], | ||
"unwantedRecommendations": [ | ||
"ms-vscode.cpptools-extension-pack" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# PlatformIO environment | ||
PIO = source ~/.platformio/penv/bin/activate && pio | ||
|
||
# Directories to watch | ||
SRC_DIR = src | ||
INCLUDE_DIR = include | ||
DATA_DIR = data | ||
LIB_DIR = ../.. | ||
|
||
# Files to watch for library changes | ||
LIB_FILES = $(shell find $(LIB_DIR)/src $(LIB_DIR)/include -type f 2>/dev/null) | ||
LIB_META = $(LIB_DIR)/library.json | ||
|
||
# Source and header files | ||
SRC_FILES = $(shell find $(SRC_DIR) -type f -name '*.cpp' -o -name '*.c' 2>/dev/null) | ||
HEADER_FILES = $(shell find $(INCLUDE_DIR) -type f -name '*.h' 2>/dev/null) | ||
DATA_FILES = $(shell find $(DATA_DIR) -type f 2>/dev/null) | ||
|
||
# Timestamp files to track last build | ||
FIRMWARE_TIMESTAMP = .pio.nosync/.firmware_timestamp | ||
FILESYSTEM_TIMESTAMP = .pio.nosync/.filesystem_timestamp | ||
UPLOAD_TIMESTAMP = .pio.nosync/.upload_timestamp | ||
|
||
# Create directories if they don't exist | ||
$(shell mkdir -p .pio.nosync) | ||
|
||
# Default target | ||
all: build-firmware build-filesystem | ||
|
||
# Build and upload firmware | ||
build-firmware: $(FIRMWARE_TIMESTAMP) | ||
$(FIRMWARE_TIMESTAMP): $(SRC_FILES) $(HEADER_FILES) $(LIB_FILES) $(LIB_META) | ||
@echo "Source files changed, rebuilding and uploading firmware..." | ||
@$(PIO) run -t upload || (echo "Firmware build failed"; exit 1) | ||
@touch $(FIRMWARE_TIMESTAMP) | ||
|
||
$(UPLOAD_TIMESTAMP): $(FIRMWARE_TIMESTAMP) | ||
@echo "Uploading firmware..." | ||
@$(PIO) run -t upload || (echo "Firmware upload failed"; exit 1) | ||
@touch $(UPLOAD_TIMESTAMP) | ||
|
||
# Build and upload filesystem | ||
build-filesystem: $(FILESYSTEM_TIMESTAMP) | ||
$(FILESYSTEM_TIMESTAMP): $(DATA_FILES) | ||
@echo "Data files changed, uploading filesystem..." | ||
@$(PIO) run -t uploadfs || (echo "Filesystem upload failed"; exit 1) | ||
@touch $(FILESYSTEM_TIMESTAMP) | ||
|
||
# Clean only build artifacts in .pio.nosync/build | ||
clean: | ||
@echo "Cleaning build artifacts in .pio.nosync/build..." | ||
@rm -f $(FIRMWARE_TIMESTAMP) $(FILESYSTEM_TIMESTAMP) | ||
@rm -rf .pio.nosync/build | ||
@echo "Note: Only removed build artifacts, all source files are preserved" | ||
|
||
# Clean everything in .pio.nosync | ||
distclean: | ||
@echo "Deep cleaning all artifacts in .pio.nosync..." | ||
@rm -rf .pio.nosync | ||
@echo "Note: Only removed .pio.nosync directory, all source files are preserved" | ||
|
||
# Helper target to show what would be rebuilt | ||
check: | ||
@echo "Checking for changes..." | ||
@if [ -n "$$(find $(SRC_FILES) $(HEADER_FILES) $(LIB_FILES) $(LIB_META) -newer $(FIRMWARE_TIMESTAMP) 2>/dev/null)" ]; then \ | ||
echo "Firmware needs rebuild"; \ | ||
fi | ||
@if [ ! -f $(FILESYSTEM_TIMESTAMP) ] || [ -n "$$(find $(DATA_FILES) -newer $(FILESYSTEM_TIMESTAMP) 2>/dev/null)" ]; then \ | ||
echo "Filesystem needs rebuild"; \ | ||
fi | ||
|
||
# Force rebuild of specific components | ||
force-firmware: | ||
@rm -f $(FIRMWARE_TIMESTAMP) | ||
@$(MAKE) build-firmware | ||
|
||
force-filesystem: | ||
@rm -f $(FILESYSTEM_TIMESTAMP) | ||
@$(MAKE) build-filesystem | ||
|
||
.PHONY: all clean distclean check build-firmware build-filesystem force-firmware force-filesystem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# KNX PlatformIO Web Example | ||
|
||
This example demonstrates how to create a web interface with real-time updates using WebSocket communication. | ||
|
||
## Features | ||
|
||
- Web server serving static files from LittleFS | ||
- WebSocket server for real-time updates | ||
- Temperature value broadcasting | ||
- Responsive file serving with proper chunked transfer | ||
|
||
## Setup | ||
|
||
1. Configure platformio.ini: | ||
```ini | ||
[env:webpage-esp8266] | ||
platform = espressif8266 | ||
board = d1 | ||
framework = arduino | ||
build_flags = | ||
-DFEATURE_WEB ; Enable web server | ||
-DFEATURE_WEBS ; Enable WebSocket server | ||
``` | ||
|
||
2. Create your application class: | ||
```cpp | ||
class knxapp : public _knxapp { | ||
public: | ||
void loop() override { | ||
_knxapp::loop(); // Call base class implementation first | ||
|
||
if (DUE(BroadcastValue)) { | ||
static float temp = 19.0; | ||
String json = "{\"temperature\":" + String(temp, 1) + "}"; | ||
_knxapp::webSocketServer.broadcast(json.c_str()); | ||
|
||
// Update temperature for next broadcast | ||
temp += 0.1; | ||
if (temp > 25.0) temp = 19.0; | ||
} | ||
} | ||
}; | ||
``` | ||
3. Prepare your web files: | ||
- Place HTML, CSS, and JavaScript files in the `data` directory | ||
- Upload filesystem using `make force-filesystem` | ||
## Web Interface | ||
1. HTML (data/index.html): | ||
```html | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>KNX Temperature</title> | ||
<link rel="stylesheet" href="style.css"> | ||
</head> | ||
<body> | ||
<div id="temperature">--.-°C</div> | ||
<script src="script.js"></script> | ||
</body> | ||
</html> | ||
``` | ||
|
||
2. JavaScript (data/script.js): | ||
```javascript | ||
let ws = null; | ||
const wsPort = 81; | ||
|
||
function connect() { | ||
ws = new WebSocket(`ws://${window.location.hostname}:${wsPort}`); | ||
|
||
ws.onmessage = function(event) { | ||
const data = JSON.parse(event.data); | ||
document.getElementById('temperature').textContent = | ||
`${data.temperature.toFixed(1)}°C`; | ||
}; | ||
|
||
ws.onclose = function() { | ||
setTimeout(connect, 1000); // Reconnect after 1 second | ||
}; | ||
} | ||
|
||
connect(); | ||
``` | ||
|
||
## Implementation Details | ||
|
||
1. Web Server: | ||
- Serves static files from LittleFS | ||
- Uses chunked transfer encoding for efficient delivery | ||
- Maintains system responsiveness with regular yield() calls | ||
|
||
2. WebSocket Server: | ||
- Runs on port 81 | ||
- Broadcasts temperature updates every second | ||
- Handles client connections automatically | ||
|
||
## Notes | ||
|
||
- Enable both FEATURE_WEB and FEATURE_WEBS in your build flags | ||
- Upload filesystem after making changes to web files | ||
- WebSocket server runs on port 81 to avoid conflicts with web server |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>KNX Temperature Monitor</title> | ||
<link rel="stylesheet" href="style.css"> | ||
</head> | ||
<body> | ||
<div class="container"> | ||
<h1>KNX Temperature Monitor</h1> | ||
<div class="temperature-display"> | ||
<div class="value">--.-</div> | ||
<div class="unit">°C</div> | ||
</div> | ||
<div class="status"> | ||
<div class="connection-status">Connecting...</div> | ||
</div> | ||
</div> | ||
<script src="script.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
document.addEventListener('DOMContentLoaded', () => { | ||
const temperatureValue = document.querySelector('.value'); | ||
const connectionStatus = document.querySelector('.connection-status'); | ||
let ws = null; | ||
let reconnectAttempts = 0; | ||
const maxReconnectAttempts = 5; | ||
|
||
function connect() { | ||
// Use secure WebSocket if page is served over HTTPS | ||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; | ||
const wsUrl = `${protocol}//${window.location.hostname}/ws`; | ||
|
||
console.log('Connecting to WebSocket:', wsUrl); | ||
ws = new WebSocket(wsUrl); | ||
|
||
ws.onopen = () => { | ||
console.log('WebSocket connected'); | ||
connectionStatus.textContent = 'Connected'; | ||
connectionStatus.classList.add('connected'); | ||
connectionStatus.classList.remove('disconnected'); | ||
reconnectAttempts = 0; | ||
}; | ||
|
||
ws.onclose = () => { | ||
console.log('WebSocket disconnected'); | ||
connectionStatus.textContent = 'Disconnected'; | ||
connectionStatus.classList.add('disconnected'); | ||
connectionStatus.classList.remove('connected'); | ||
|
||
// Attempt to reconnect | ||
if (reconnectAttempts < maxReconnectAttempts) { | ||
reconnectAttempts++; | ||
connectionStatus.textContent = `Reconnecting (${reconnectAttempts}/${maxReconnectAttempts})...`; | ||
setTimeout(connect, 3000); | ||
} else { | ||
connectionStatus.textContent = 'Connection failed. Please refresh the page.'; | ||
} | ||
}; | ||
|
||
ws.onerror = (error) => { | ||
console.error('WebSocket error:', error); | ||
}; | ||
|
||
ws.onmessage = (event) => { | ||
console.log('WebSocket message:', event.data); | ||
try { | ||
const data = JSON.parse(event.data); | ||
if (data.temperature !== undefined) { | ||
temperatureValue.textContent = data.temperature.toFixed(1); | ||
} | ||
} catch (e) { | ||
console.error('Error parsing WebSocket message:', e); | ||
} | ||
}; | ||
} | ||
|
||
// Initial connection | ||
connect(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
* { | ||
margin: 0; | ||
padding: 0; | ||
box-sizing: border-box; | ||
} | ||
|
||
body { | ||
font-family: Arial, sans-serif; | ||
background-color: #f0f0f0; | ||
min-height: 100vh; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
} | ||
|
||
.container { | ||
background-color: white; | ||
padding: 2rem; | ||
border-radius: 10px; | ||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); | ||
text-align: center; | ||
} | ||
|
||
h1 { | ||
color: #333; | ||
margin-bottom: 2rem; | ||
font-size: 1.5rem; | ||
} | ||
|
||
.temperature-display { | ||
display: flex; | ||
justify-content: center; | ||
align-items: baseline; | ||
margin: 2rem 0; | ||
font-size: 3rem; | ||
color: #2196F3; | ||
} | ||
|
||
.value { | ||
font-weight: bold; | ||
} | ||
|
||
.unit { | ||
margin-left: 0.5rem; | ||
font-size: 2rem; | ||
} | ||
|
||
.status { | ||
margin-top: 1rem; | ||
} | ||
|
||
.connection-status { | ||
font-size: 0.9rem; | ||
color: #666; | ||
} | ||
|
||
.connected { | ||
color: #4CAF50; | ||
} | ||
|
||
.disconnected { | ||
color: #f44336; | ||
} |
Oops, something went wrong.