diff --git a/assets/app.css b/assets/app.css
index 0e06f43..98866f8 100755
--- a/assets/app.css
+++ b/assets/app.css
@@ -1493,7 +1493,7 @@ body.is-mobile-ui #camera-modal {
position: absolute;
left: 0;
right: 0;
- top: 0;
+ bottom: 0;
border-radius: inherit;
background:
linear-gradient(180deg, rgba(103, 214, 255, 0.96) 0%, rgba(126, 236, 220, 0.94) 58%, rgba(188, 255, 242, 0.96) 100%);
@@ -1507,7 +1507,7 @@ body.is-mobile-ui #camera-modal {
.entity-modal__cover-handle {
position: absolute;
left: 50%;
- top: -10px;
+ bottom: -10px;
width: 36px;
height: 20px;
border-radius: 999px;
diff --git a/assets/app.js b/assets/app.js
index e6d3570..0f4ab16 100755
--- a/assets/app.js
+++ b/assets/app.js
@@ -2355,10 +2355,7 @@
const rail = document.createElement('div');
rail.className = 'entity-modal__rail entity-modal__rail--cover';
- const currentPosition = Number(entity.attributes?.current_position);
- const initialValue = Number.isFinite(currentPosition)
- ? Math.max(0, Math.min(100, currentPosition))
- : (String(entity.state || '').toLowerCase() === 'open' ? 100 : 0);
+ const initialValue = coverPositionValue(entity);
const valueRow = document.createElement('div');
valueRow.className = 'entity-modal__cover-meta';
@@ -2372,13 +2369,32 @@
value.textContent = `${initialValue}%`;
valueRow.append(label, value);
+ const actions = document.createElement('div');
+ actions.className = 'entity-modal__actions entity-modal__actions--vertical';
+
+ const openBtn = createButton('Открыть', null, 'mdi:arrow-up', 'mushroom-button mushroom-button--small mushroom-button--square');
+ openBtn.addEventListener('click', () => handleEntityAction(entity, 'open'));
+
+ const stopBtn = createButton('Стоп', null, 'mdi:stop', 'mushroom-button mushroom-button--small mushroom-button--square');
+ stopBtn.addEventListener('click', () => handleEntityAction(entity, 'stop'));
+
+ const closeBtn = createButton('Закрыть', null, 'mdi:arrow-down', 'mushroom-button mushroom-button--small mushroom-button--square');
+ closeBtn.addEventListener('click', () => handleEntityAction(entity, 'close'));
+
+ actions.append(openBtn, stopBtn, closeBtn);
+
const progress = document.createElement('div');
progress.className = 'entity-modal__cover-track';
+ progress.tabIndex = 0;
+ progress.setAttribute('role', 'slider');
+ progress.setAttribute('aria-label', 'Позиция жалюзи');
+ progress.setAttribute('aria-valuemin', '0');
+ progress.setAttribute('aria-valuemax', '100');
const fill = document.createElement('div');
fill.className = 'entity-modal__cover-fill';
fill.style.height = `${initialValue}%`;
- fill.style.top = '0';
+ fill.style.bottom = '0';
fill.style.width = '100%';
progress.appendChild(fill);
@@ -2386,10 +2402,14 @@
handle.className = 'entity-modal__cover-handle';
progress.appendChild(handle);
+ let currentValue = initialValue;
const syncValue = (nextValue) => {
- fill.style.height = `${nextValue}%`;
- handle.style.top = nextValue <= 0 ? 'calc(100% - 10px)' : `calc(${nextValue}% - 10px)`;
- value.textContent = `${nextValue}%`;
+ currentValue = Math.max(0, Math.min(100, Math.round(nextValue)));
+ fill.style.height = `${currentValue}%`;
+ handle.style.bottom = `calc(${currentValue}% - 10px)`;
+ value.textContent = `${currentValue}%`;
+ progress.setAttribute('aria-valuenow', String(currentValue));
+ progress.setAttribute('aria-valuetext', `${currentValue}%`);
};
syncValue(initialValue);
@@ -2398,7 +2418,6 @@
const ratio = 1 - ((clientY - rect.top) / rect.height);
const nextValue = Math.max(0, Math.min(100, Math.round(ratio * 100)));
syncValue(nextValue);
- handleCoverPosition(entity, nextValue);
};
let dragPointerId = null;
@@ -2415,6 +2434,7 @@
window.removeEventListener('pointermove', onPointerMove);
window.removeEventListener('pointerup', onPointerUp);
window.removeEventListener('pointercancel', onPointerUp);
+ handleCoverPosition(entity, currentValue);
};
progress.addEventListener('pointerdown', (event) => {
@@ -2427,22 +2447,29 @@
window.addEventListener('pointercancel', onPointerUp, { passive: false });
});
+ progress.addEventListener('keydown', (event) => {
+ const step = event.shiftKey ? 10 : 5;
+ if (event.key === 'ArrowUp' || event.key === 'ArrowRight') {
+ event.preventDefault();
+ syncValue(currentValue + step);
+ handleCoverPosition(entity, currentValue);
+ } else if (event.key === 'ArrowDown' || event.key === 'ArrowLeft') {
+ event.preventDefault();
+ syncValue(currentValue - step);
+ handleCoverPosition(entity, currentValue);
+ } else if (event.key === 'Home') {
+ event.preventDefault();
+ syncValue(0);
+ handleCoverPosition(entity, 0);
+ } else if (event.key === 'End') {
+ event.preventDefault();
+ syncValue(100);
+ handleCoverPosition(entity, 100);
+ }
+ });
+
rail.append(valueRow, progress);
-
- const buttons = document.createElement('div');
- buttons.className = 'entity-modal__actions entity-modal__actions--vertical';
-
- const openBtn = createButton('Открыть', null, 'mdi:arrow-up', 'mushroom-button mushroom-button--small mushroom-button--square');
- openBtn.addEventListener('click', () => handleEntityService(entity, 'open'));
-
- const stopBtn = createButton('Стоп', null, 'mdi:stop', 'mushroom-button mushroom-button--small mushroom-button--square');
- stopBtn.addEventListener('click', () => handleEntityService(entity, 'stop'));
-
- const closeBtn = createButton('Закрыть', null, 'mdi:arrow-down', 'mushroom-button mushroom-button--small mushroom-button--square');
- closeBtn.addEventListener('click', () => handleEntityService(entity, 'close'));
-
- buttons.append(openBtn, stopBtn, closeBtn);
- wrap.append(rail, buttons);
+ wrap.append(rail, actions);
return wrap;
}
@@ -2590,6 +2617,16 @@
return labels[key] || String(value ?? '—').replace(/_/g, ' ');
}
+ function coverPositionValue(entity) {
+ const currentPosition = Number(entity?.attributes?.current_position);
+ if (Number.isFinite(currentPosition)) {
+ return Math.max(0, Math.min(100, Math.round(currentPosition)));
+ }
+
+ const state = String(entity?.state || '').toLowerCase();
+ return state === 'open' || state === 'opening' ? 100 : 0;
+ }
+
async function handleEntityService(entity, command, value = null, patch = null) {
try {
if (patch) {
@@ -2762,11 +2799,10 @@
function renderCoverCard(entity, options = {}) {
const card = document.createElement('article');
- const isOpen = ['open', 'opening'].includes(String(entity.state).toLowerCase());
- const currentPosition = Number(entity.attributes?.current_position);
- const hasVisiblePosition = Number.isFinite(currentPosition)
- ? currentPosition > 0
- : isOpen;
+ const currentPosition = coverPositionValue(entity);
+ const coverState = String(entity.state).toLowerCase();
+ const isOpen = ['open', 'opening'].includes(coverState);
+ const hasVisiblePosition = currentPosition > 0 || isOpen;
card.className = `grid-card grid-card--cover ${!options.isMain && isOpen ? 'is-active' : ''}`;
card.dataset.entityId = entity.entity_id;
card.tabIndex = 0;
@@ -2796,7 +2832,7 @@
progress.className = 'cover-progress';
const bar = document.createElement('div');
bar.className = 'cover-progress__value';
- const pos = Number.isFinite(currentPosition) ? currentPosition : 100;
+ const pos = currentPosition > 0 ? currentPosition : 100;
bar.style.width = `${Math.max(0, Math.min(100, pos))}%`;
progress.appendChild(bar);
diff --git a/index.php b/index.php
index d44f22b..4480468 100755
--- a/index.php
+++ b/index.php
@@ -23,8 +23,8 @@ $appTitle = htmlspecialchars((string)($config['app']['title'] ?? 'Wall Panel'),
-
-
+
+
diff --git a/lib/config.php b/lib/config.php
index 722cda3..27af67f 100755
--- a/lib/config.php
+++ b/lib/config.php
@@ -10,6 +10,7 @@ function app_default_config(): array
'main_room_name' => 'Главная',
'main_room_icon' => 'mdi:home',
'edit_mode' => false,
+ 'battery_history_hours' => 4320,
],
'home_assistant' => [
'base_url' => '',
@@ -114,4 +115,3 @@ function app_save_json_file(string $path, array $data): void
file_put_contents($path, $json . PHP_EOL, LOCK_EX);
}
-
diff --git a/lib/dashboard.php b/lib/dashboard.php
index 984f50b..49a81f5 100755
--- a/lib/dashboard.php
+++ b/lib/dashboard.php
@@ -906,6 +906,11 @@ function app_battery_summary_text(array $counts, int $total): string
: 'Нет батареек';
}
+function app_battery_history_hours(array $config): int
+{
+ return max(24, (int)($config['app']['battery_history_hours'] ?? 4320));
+}
+
function app_battery_room(array $config, array $haData, array $rooms, HomeAssistantClient $client, bool $refreshForecast = false): array
{
$entityIndex = app_entity_index($config, $haData);
@@ -927,6 +932,7 @@ function app_battery_room(array $config, array $haData, array $rooms, HomeAssist
$cacheItems = is_array($cache['items'] ?? null) ? $cache['items'] : [];
$cacheChanged = false;
$now = time();
+ $historyHours = app_battery_history_hours($config);
$batteryEntities = [];
$deviceGroups = [];
@@ -1013,20 +1019,21 @@ function app_battery_room(array $config, array $haData, array $rooms, HomeAssist
'forecast_reason' => null,
];
- $shouldRefresh = $refreshForecast
+ $cachedAt = (int)($cacheEntry['loaded_at'] ?? 0);
+ $cacheMatchesWindow = (int)($cacheEntry['history_hours'] ?? 0) === $historyHours;
+ $freshEnough = $cachedAt > 0 && ($now - $cachedAt) < 6 * 3600 && $cacheMatchesWindow;
+ $shouldRefresh = ($refreshForecast || !$cacheMatchesWindow)
&& $percent !== null
&& !in_array($status, ['unavailable', 'unknown'], true);
- $cachedAt = (int)($cacheEntry['loaded_at'] ?? 0);
- $freshEnough = $cachedAt > 0 && ($now - $cachedAt) < 6 * 3600;
-
if ($shouldRefresh && (!$freshEnough || !isset($cacheEntry['forecast_minutes_left']))) {
try {
- $history = $client->fetchEntityHistory($entityId, 168);
+ $history = $client->fetchEntityHistory($entityId, $historyHours);
$points = app_battery_history_points($history);
$forecast = app_battery_forecast_from_points($points, $percent);
$cacheItems[$entityId] = [
'loaded_at' => $now,
+ 'history_hours' => $historyHours,
'points' => $points,
'forecast_minutes_left' => $forecast['forecast_minutes_left'],
'forecast_text' => $forecast['forecast_text'],
@@ -1045,7 +1052,7 @@ function app_battery_room(array $config, array $haData, array $rooms, HomeAssist
];
}
}
- } elseif (is_array($cacheEntry) && isset($cacheEntry['forecast_minutes_left'])) {
+ } elseif ($cacheMatchesWindow && is_array($cacheEntry) && isset($cacheEntry['forecast_minutes_left'])) {
$forecast = [
'forecast_minutes_left' => isset($cacheEntry['forecast_minutes_left']) ? (int)$cacheEntry['forecast_minutes_left'] : null,
'forecast_text' => isset($cacheEntry['forecast_text']) ? (string)$cacheEntry['forecast_text'] : null,
diff --git a/storage/battery_cache.json b/storage/battery_cache.json
index 4d4aded..8fe16a8 100755
--- a/storage/battery_cache.json
+++ b/storage/battery_cache.json
@@ -1,10 +1,11 @@
{
"items": {
"sensor.garage_motion_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 100
},
{
@@ -22,15 +23,16 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": 0,
+ "forecast_slope_per_hour": -0,
"forecast_reason": "Нет заметного разряда",
"percent": 100
},
"sensor.garage_light_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 100
},
{
@@ -48,15 +50,16 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": 0,
+ "forecast_slope_per_hour": -0,
"forecast_reason": "Нет заметного разряда",
"percent": 100
},
"sensor.garage_door_motion_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 100
},
{
@@ -74,15 +77,16 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": 0,
+ "forecast_slope_per_hour": -0,
"forecast_reason": "Нет заметного разряда",
"percent": 100
},
"sensor.stair_up_motion_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 100
},
{
@@ -100,15 +104,16 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": 0,
+ "forecast_slope_per_hour": -0,
"forecast_reason": "Нет заметного разряда",
"percent": 100
},
"sensor.stair_down_motion_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 100
},
{
@@ -126,15 +131,16 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": 0,
+ "forecast_slope_per_hour": -0,
"forecast_reason": "Нет заметного разряда",
"percent": 100
},
"sensor.stair_light_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 100
},
{
@@ -152,15 +158,16 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": 0,
+ "forecast_slope_per_hour": -0,
"forecast_reason": "Нет заметного разряда",
"percent": 100
},
"sensor.door_sensor_2_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 90
},
{
@@ -178,15 +185,16 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": 0,
+ "forecast_slope_per_hour": -0,
"forecast_reason": "Нет заметного разряда",
"percent": 90
},
"sensor.wleak_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 100
},
{
@@ -204,15 +212,16 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": 0,
+ "forecast_slope_per_hour": -0,
"forecast_reason": "Нет заметного разряда",
"percent": 100
},
"sensor.0xa4c138433d675809_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 1
},
{
@@ -235,10 +244,11 @@
"percent": 1
},
"sensor.0xa4c138997cb4fdd1_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 100
},
{
@@ -256,15 +266,16 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": 0,
+ "forecast_slope_per_hour": -0,
"forecast_reason": "Нет заметного разряда",
"percent": 100
},
"sensor.printer_knopka_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 74
},
{
@@ -282,41 +293,43 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": -0,
- "forecast_reason": "Нет заметного разряда",
- "percent": 74
- },
- "sensor.lestnitsa_dvizhenie_2_etazh_battery": {
- "loaded_at": 1773993995,
- "points": [
- {
- "timestamp": 1773389195,
- "value": 100
- },
- {
- "timestamp": 1773411344,
- "value": 100
- },
- {
- "timestamp": 1773414678,
- "value": 100
- },
- {
- "timestamp": 1773417954,
- "value": 100
- }
- ],
- "forecast_minutes_left": null,
- "forecast_text": null,
"forecast_slope_per_hour": 0,
"forecast_reason": "Нет заметного разряда",
+ "percent": 74
+ },
+ "sensor.lestnitsa_dvizhenie_2_etazh_battery": {
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
+ "points": [
+ {
+ "timestamp": 1773403910,
+ "value": 100
+ },
+ {
+ "timestamp": 1773411344,
+ "value": 100
+ },
+ {
+ "timestamp": 1773414678,
+ "value": 100
+ },
+ {
+ "timestamp": 1773417954,
+ "value": 100
+ }
+ ],
+ "forecast_minutes_left": null,
+ "forecast_text": null,
+ "forecast_slope_per_hour": -0,
+ "forecast_reason": "Нет заметного разряда",
"percent": 100
},
"sensor.spalnia_knopka_girliand_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 29
},
{
@@ -334,15 +347,16 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": -0,
+ "forecast_slope_per_hour": 0,
"forecast_reason": "Нет заметного разряда",
"percent": 29
},
"sensor.ulitsa_temperatura_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 63
},
{
@@ -365,10 +379,11 @@
"percent": 63
},
"sensor.0x44e2f8fffeb65d8e_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008698,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403899,
"value": 70
},
{
@@ -394,35 +409,28 @@
{
"timestamp": 1773466259,
"value": 60
+ },
+ {
+ "timestamp": 1773488508,
+ "value": 65
+ },
+ {
+ "timestamp": 1773488530,
+ "value": 50
}
],
- "forecast_minutes_left": 10497,
- "forecast_text": "≈ 7д 6ч до разряда",
- "forecast_slope_per_hour": -0.2572,
+ "forecast_minutes_left": 5642,
+ "forecast_text": "≈ 3д 22ч до разряда",
+ "forecast_slope_per_hour": -0.4786,
"forecast_reason": null,
"percent": 45
},
"sensor.0x54ef4410009a6a11_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008698,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
- "value": 95
- },
- {
- "timestamp": 1773391484,
- "value": 94
- },
- {
- "timestamp": 1773394714,
- "value": 95
- },
- {
- "timestamp": 1773398043,
- "value": 92
- },
- {
- "timestamp": 1773401498,
+ "timestamp": 1773403899,
"value": 95
},
{
@@ -508,19 +516,36 @@
{
"timestamp": 1773475444,
"value": 93
+ },
+ {
+ "timestamp": 1773478854,
+ "value": 95
+ },
+ {
+ "timestamp": 1773481995,
+ "value": 90
+ },
+ {
+ "timestamp": 1773485044,
+ "value": 92
+ },
+ {
+ "timestamp": 1773488293,
+ "value": 70
}
],
- "forecast_minutes_left": 121234,
- "forecast_text": "≈ 84д 4ч до разряда",
- "forecast_slope_per_hour": -0.046,
+ "forecast_minutes_left": 13952,
+ "forecast_text": "≈ 9д 16ч до разряда",
+ "forecast_slope_per_hour": -0.4043,
"forecast_reason": null,
- "percent": 93
+ "percent": 94
},
"sensor.0x00124b0035558456_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 82
},
{
@@ -538,15 +563,16 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": 0,
+ "forecast_slope_per_hour": -0,
"forecast_reason": "Нет заметного разряда",
"percent": 82
},
"sensor.0xa4c13874f5fdfd2a_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 92.5
},
{
@@ -569,10 +595,11 @@
"percent": 92
},
"sensor.0x54ef44100119db20_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 100
},
{
@@ -590,12 +617,13 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": 0,
+ "forecast_slope_per_hour": -0,
"forecast_reason": "Нет заметного разряда",
"percent": 100
},
"sensor.door_sensor_spalnya_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [],
"forecast_minutes_left": null,
"forecast_text": null,
@@ -604,10 +632,11 @@
"percent": 100
},
"sensor.0x0ceff6fffe6cffc4_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 45
},
{
@@ -645,19 +674,28 @@
{
"timestamp": 1773466260,
"value": 45
+ },
+ {
+ "timestamp": 1773488510,
+ "value": 50
+ },
+ {
+ "timestamp": 1773488531,
+ "value": 45
}
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": 0.0849,
+ "forecast_slope_per_hour": 0.066,
"forecast_reason": "Заряд не падает",
- "percent": 50
+ "percent": 55
},
"sensor.0x0ceff6fffe6cdee0_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 0
},
{
@@ -677,21 +715,14 @@
"forecast_text": null,
"forecast_slope_per_hour": 0,
"forecast_reason": "Нет заметного разряда",
- "percent": 55
+ "percent": 60
},
"sensor.0x705464fffe43dee0_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008698,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
- "value": 50
- },
- {
- "timestamp": 1773402386,
- "value": 55
- },
- {
- "timestamp": 1773402406,
+ "timestamp": 1773403899,
"value": 50
},
{
@@ -713,19 +744,28 @@
{
"timestamp": 1773466239,
"value": 50
+ },
+ {
+ "timestamp": 1773479774,
+ "value": 45
+ },
+ {
+ "timestamp": 1773488510,
+ "value": 50
}
],
- "forecast_minutes_left": 44180,
- "forecast_text": "≈ 30д 16ч до разряда",
- "forecast_slope_per_hour": -0.0475,
+ "forecast_minutes_left": 15830,
+ "forecast_text": "≈ 10д 23ч до разряда",
+ "forecast_slope_per_hour": -0.1327,
"forecast_reason": null,
"percent": 35
},
"sensor.0xa4c138259d164c22_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 88.5
},
{
@@ -743,41 +783,43 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": 0,
- "forecast_reason": "Нет заметного разряда",
- "percent": 88.5
- },
- "sensor.0xa4c138fe1cdd2a21_battery": {
- "loaded_at": 1773993995,
- "points": [
- {
- "timestamp": 1773389195,
- "value": 87.5
- },
- {
- "timestamp": 1773411344,
- "value": 87.5
- },
- {
- "timestamp": 1773414678,
- "value": 87.5
- },
- {
- "timestamp": 1773417954,
- "value": 87.5
- }
- ],
- "forecast_minutes_left": null,
- "forecast_text": null,
"forecast_slope_per_hour": -0,
"forecast_reason": "Нет заметного разряда",
+ "percent": 88.5
+ },
+ "sensor.0xa4c138fe1cdd2a21_battery": {
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
+ "points": [
+ {
+ "timestamp": 1773403910,
+ "value": 87.5
+ },
+ {
+ "timestamp": 1773411344,
+ "value": 87.5
+ },
+ {
+ "timestamp": 1773414678,
+ "value": 87.5
+ },
+ {
+ "timestamp": 1773417954,
+ "value": 87.5
+ }
+ ],
+ "forecast_minutes_left": null,
+ "forecast_text": null,
+ "forecast_slope_per_hour": 0,
+ "forecast_reason": "Нет заметного разряда",
"percent": 85.5
},
"sensor.spalnya_temp_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 3
},
{
@@ -803,15 +845,16 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": null,
- "forecast_reason": "Батарея уже разряжена",
- "percent": 0
+ "forecast_slope_per_hour": 0.348,
+ "forecast_reason": "Заряд не падает",
+ "percent": 3
},
"sensor.kukhnia_temperatura_battery": {
- "loaded_at": 1773993995,
+ "loaded_at": 1774008710,
+ "history_hours": 4320,
"points": [
{
- "timestamp": 1773389195,
+ "timestamp": 1773403910,
"value": 90
},
{
@@ -829,9 +872,9 @@
],
"forecast_minutes_left": null,
"forecast_text": null,
- "forecast_slope_per_hour": 0,
+ "forecast_slope_per_hour": -0,
"forecast_reason": "Нет заметного разряда",
- "percent": 90
+ "percent": 83
}
}
}
diff --git a/storage/popup_state.json b/storage/popup_state.json
index 8b4269f..6e3da04 100755
--- a/storage/popup_state.json
+++ b/storage/popup_state.json
@@ -1,6 +1,6 @@
{
"active": false,
- "sensor_entity_id": "binary_sensor.barn_all_occupancy",
- "opened_at": 1774006226,
+ "sensor_entity_id": "binary_sensor.doorbell_all_occupancy",
+ "opened_at": 1774098512,
"expires_at": null
}
diff --git a/wallpanell.code-workspace b/wallpanell.code-workspace
new file mode 100755
index 0000000..876a149
--- /dev/null
+++ b/wallpanell.code-workspace
@@ -0,0 +1,8 @@
+{
+ "folders": [
+ {
+ "path": "."
+ }
+ ],
+ "settings": {}
+}
\ No newline at end of file