Compare commits
5 Commits
groups_and
...
ui_fix_the
| Author | SHA1 | Date | |
|---|---|---|---|
|
2e24c259cb
|
|||
|
bbf280bdf4
|
|||
|
a7d778b211
|
|||
|
a7d8afc98b
|
|||
|
a4ae8a2f6c
|
@@ -246,6 +246,23 @@ class RedisState:
|
||||
|
||||
await self._execute_with_retry(_expire, key, ttl_secs)
|
||||
|
||||
async def delete(self, key: str) -> None:
|
||||
"""
|
||||
Delete a key from Redis.
|
||||
|
||||
Args:
|
||||
key: Redis key to delete
|
||||
|
||||
Example:
|
||||
>>> state = RedisState("redis://localhost:6379/0")
|
||||
>>> await state.set("rules:r1:temp", "22.5")
|
||||
>>> await state.delete("rules:r1:temp")
|
||||
"""
|
||||
async def _delete(client, k):
|
||||
await client.delete(k)
|
||||
|
||||
await self._execute_with_retry(_delete, key)
|
||||
|
||||
async def close(self) -> None:
|
||||
"""
|
||||
Close Redis connection and cleanup resources.
|
||||
|
||||
@@ -365,32 +365,57 @@
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.temp-controls {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
/* Thermostat Slider Styles */
|
||||
.thermostat-slider-control {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.temp-button {
|
||||
flex: 1;
|
||||
padding: 0.75rem;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 1.125rem;
|
||||
font-weight: 700;
|
||||
.thermostat-slider-label {
|
||||
font-size: 0.875rem;
|
||||
color: #666;
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.thermostat-slider {
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
background: linear-gradient(to right, #667eea 0%, #764ba2 100%);
|
||||
outline: none;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
background: #667eea;
|
||||
color: white;
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
.temp-button:hover {
|
||||
background: #5568d3;
|
||||
.thermostat-slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
background: white;
|
||||
border: 3px solid #667eea;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.temp-button:active {
|
||||
transform: scale(0.95);
|
||||
.thermostat-slider::-moz-range-thumb {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
background: white;
|
||||
border: 3px solid #667eea;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.thermostat-slider-range {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* Contact Sensor Styles */
|
||||
@@ -398,6 +423,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
|
||||
padding: 1rem;
|
||||
background: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
@@ -965,13 +991,23 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="temp-controls">
|
||||
<button class="temp-button" onclick="adjustTarget('{{ device.device_id }}', -1.0)">
|
||||
-1.0
|
||||
</button>
|
||||
<button class="temp-button" onclick="adjustTarget('{{ device.device_id }}', 1.0)">
|
||||
+1.0
|
||||
</button>
|
||||
<div class="thermostat-slider-control">
|
||||
<label for="slider-{{ device.device_id }}" class="thermostat-slider-label">
|
||||
🎯 Zieltemperatur: <span id="thermostat-slider-value-{{ device.device_id }}">21.0</span>°C
|
||||
</label>
|
||||
<input type="range"
|
||||
min="5"
|
||||
max="30"
|
||||
step="0.5"
|
||||
value="21.0"
|
||||
class="thermostat-slider"
|
||||
id="slider-{{ device.device_id }}"
|
||||
oninput="updateThermostatSliderValue('{{ device.device_id }}', this.value)"
|
||||
onchange="setThermostatTarget('{{ device.device_id }}', this.value)">
|
||||
<div class="thermostat-slider-range">
|
||||
<span>5°C</span>
|
||||
<span>30°C</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% elif device.type == "contact" or device.type == "contact_sensor" %}
|
||||
@@ -1327,6 +1363,8 @@
|
||||
function updateThermostatUI(deviceId, current, target, mode) {
|
||||
const currentSpan = document.getElementById(`state-${deviceId}-current`);
|
||||
const targetSpan = document.getElementById(`state-${deviceId}-target`);
|
||||
const slider = document.getElementById(`slider-${deviceId}`);
|
||||
const sliderValueSpan = document.getElementById(`thermostat-slider-value-${deviceId}`);
|
||||
|
||||
if (current !== undefined && currentSpan) {
|
||||
currentSpan.textContent = current.toFixed(1);
|
||||
@@ -1336,6 +1374,14 @@
|
||||
if (targetSpan) {
|
||||
targetSpan.textContent = target.toFixed(1);
|
||||
}
|
||||
// Sync slider with actual state
|
||||
if (slider) {
|
||||
slider.value = target;
|
||||
}
|
||||
// Sync slider value display
|
||||
if (sliderValueSpan) {
|
||||
sliderValueSpan.textContent = target.toFixed(1);
|
||||
}
|
||||
thermostatTargets[deviceId] = target;
|
||||
}
|
||||
}
|
||||
@@ -1733,6 +1779,49 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Update thermostat slider value display while dragging
|
||||
function updateThermostatSliderValue(deviceId, value) {
|
||||
const valueSpan = document.getElementById(`thermostat-slider-value-${deviceId}`);
|
||||
if (valueSpan) {
|
||||
valueSpan.textContent = parseFloat(value).toFixed(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Set thermostat target temperature when slider is released
|
||||
async function setThermostatTarget(deviceId, value) {
|
||||
try {
|
||||
const targetTemp = parseFloat(value);
|
||||
|
||||
const response = await fetch(api(`/devices/${deviceId}/set`), {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
type: 'thermostat',
|
||||
payload: {
|
||||
target: targetTemp
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json();
|
||||
throw new Error(error.detail || 'Request failed');
|
||||
}
|
||||
|
||||
console.log(`Thermostat ${deviceId} target set to ${targetTemp}°C`);
|
||||
|
||||
addEvent({
|
||||
action: 'thermostat_set',
|
||||
device_id: deviceId,
|
||||
target_temperature: targetTemp
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to set thermostat target:', error);
|
||||
showToast(`Fehler beim Setzen der Zieltemperatur: ${error.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Execute group action
|
||||
async function setGroup(groupId, power, buttonElement) {
|
||||
const allButtons = buttonElement.parentElement.querySelectorAll('button');
|
||||
|
||||
Reference in New Issue
Block a user