This commit is contained in:
Striker72rus 2026-03-21 16:34:52 +03:00
parent d0062c0a64
commit c272d88e49
8 changed files with 292 additions and 198 deletions

View File

@ -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;

View File

@ -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);

View File

@ -23,8 +23,8 @@ $appTitle = htmlspecialchars((string)($config['app']['title'] ?? 'Wall Panel'),
<script>
window.APP_BOOTSTRAP = <?= json_encode($bootstrap, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
</script>
<link rel="stylesheet" href="assets/app.css?v=0.25">
<script src="assets/app.js?v=0.25" defer></script>
<link rel="stylesheet" href="assets/app.css?v=0.26">
<script src="assets/app.js?v=0.26" defer></script>
</head>
<body>
<div class="app-shell">

View File

@ -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);
}

View File

@ -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,

View File

@ -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
}
}
}

View File

@ -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
}

8
wallpanell.code-workspace Executable file
View File

@ -0,0 +1,8 @@
{
"folders": [
{
"path": "."
}
],
"settings": {}
}