2023-11-17 00:05:35 +00:00
|
|
|
<script lang="ts">
|
2023-11-30 20:53:37 +00:00
|
|
|
import { PUBLIC_BASE_URL } from '$lib/config';
|
2023-11-17 00:05:35 +00:00
|
|
|
|
|
|
|
import { _ } from 'svelte-i18n';
|
2023-11-19 19:27:22 +00:00
|
|
|
import { writable } from 'svelte/store';
|
|
|
|
import {
|
|
|
|
Button,
|
|
|
|
ButtonGroup,
|
|
|
|
Card,
|
|
|
|
CardBody,
|
|
|
|
CardHeader,
|
|
|
|
CardTitle,
|
|
|
|
Col,
|
|
|
|
Input,
|
|
|
|
Progress,
|
2023-11-21 15:05:00 +00:00
|
|
|
Tooltip,
|
2023-11-19 19:27:22 +00:00
|
|
|
Row
|
2024-09-03 10:11:14 +00:00
|
|
|
} from '@sveltestrap/sveltestrap';
|
2023-11-17 00:05:35 +00:00
|
|
|
import Rendered from './Rendered.svelte';
|
|
|
|
|
2023-11-19 19:27:22 +00:00
|
|
|
export let settings;
|
|
|
|
export let status: writable<object>;
|
2023-11-17 00:05:35 +00:00
|
|
|
|
2024-08-31 15:56:35 +00:00
|
|
|
// Function to split array into chunks
|
|
|
|
const chunkArray = (array, chunkSize) => {
|
|
|
|
const result = [];
|
|
|
|
for (let i = 0; i < array.length; i += chunkSize) {
|
|
|
|
result.push(array.slice(i, i + chunkSize));
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
let buttonChunks = chunkArray([], 6);
|
|
|
|
|
2023-11-19 19:27:22 +00:00
|
|
|
const toTime = (secs: number) => {
|
|
|
|
var hours = Math.floor(secs / (60 * 60));
|
2023-11-17 00:05:35 +00:00
|
|
|
|
2023-11-19 19:27:22 +00:00
|
|
|
var divisor_for_minutes = secs % (60 * 60);
|
|
|
|
var minutes = Math.floor(divisor_for_minutes / 60);
|
2023-11-17 00:05:35 +00:00
|
|
|
|
2023-11-19 19:27:22 +00:00
|
|
|
var divisor_for_seconds = divisor_for_minutes % 60;
|
|
|
|
var seconds = Math.ceil(divisor_for_seconds);
|
2023-11-17 00:05:35 +00:00
|
|
|
|
2023-11-19 19:27:22 +00:00
|
|
|
var obj = {
|
|
|
|
h: hours,
|
|
|
|
m: minutes,
|
|
|
|
s: seconds
|
|
|
|
};
|
|
|
|
return obj;
|
|
|
|
};
|
2023-11-17 00:05:35 +00:00
|
|
|
|
2023-11-19 19:27:22 +00:00
|
|
|
const toUptimestring = (secs: number): string => {
|
|
|
|
let time = toTime(secs);
|
2023-11-17 00:05:35 +00:00
|
|
|
|
2023-11-19 19:27:22 +00:00
|
|
|
return `${time.h}h ${time.m}m ${time.s}s`;
|
|
|
|
};
|
2023-11-17 12:12:22 +00:00
|
|
|
|
2023-11-19 19:27:22 +00:00
|
|
|
let memoryFreePercent: number = 50;
|
2023-11-21 15:05:00 +00:00
|
|
|
let rssiPercent: number = 50;
|
|
|
|
let wifiStrengthColor: string = 'info';
|
2023-11-19 19:27:22 +00:00
|
|
|
let lightMode: boolean = false;
|
2023-11-17 00:05:35 +00:00
|
|
|
|
2023-11-19 19:27:22 +00:00
|
|
|
status.subscribe((value: object) => {
|
|
|
|
memoryFreePercent = Math.round((value.espFreeHeap / value.espHeapSize) * 100);
|
2023-11-21 15:05:00 +00:00
|
|
|
|
|
|
|
rssiPercent = Math.round(((value.rssi + 120) / (-30 + 120)) * 100);
|
|
|
|
|
|
|
|
if (value.rssi > -55) {
|
|
|
|
wifiStrengthColor = 'success';
|
|
|
|
} else if (value.rssi < -87) {
|
|
|
|
wifiStrengthColor = 'warning';
|
|
|
|
} else {
|
|
|
|
wifiStrengthColor = 'info';
|
|
|
|
}
|
2023-11-19 19:27:22 +00:00
|
|
|
});
|
2023-11-17 12:12:22 +00:00
|
|
|
|
2023-11-19 19:27:22 +00:00
|
|
|
settings.subscribe((value: object) => {
|
|
|
|
lightMode = value.bgColor > value.fgColor;
|
2024-08-31 15:56:35 +00:00
|
|
|
|
|
|
|
if (value.screens) buttonChunks = chunkArray(value.screens, 5);
|
2023-11-19 19:27:22 +00:00
|
|
|
});
|
2023-11-17 00:05:35 +00:00
|
|
|
|
2023-11-19 19:27:22 +00:00
|
|
|
const setScreen = (id: number) => () => {
|
|
|
|
fetch(`${PUBLIC_BASE_URL}/api/show/screen/${id}`).catch(() => {});
|
|
|
|
};
|
2023-11-17 12:12:22 +00:00
|
|
|
|
2024-09-04 23:59:05 +00:00
|
|
|
const setCurrency = (c: string) => () => {
|
|
|
|
fetch(`${PUBLIC_BASE_URL}/api/show/currency/${c}`).catch(() => {});
|
|
|
|
};
|
|
|
|
|
2023-11-19 19:27:22 +00:00
|
|
|
const toggleTimer = (currentStatus: boolean) => (e: Event) => {
|
|
|
|
e.preventDefault();
|
|
|
|
if (currentStatus) {
|
|
|
|
fetch(`${PUBLIC_BASE_URL}/api/action/pause`);
|
|
|
|
} else {
|
|
|
|
fetch(`${PUBLIC_BASE_URL}/api/action/timer_restart`);
|
|
|
|
}
|
|
|
|
};
|
2024-08-31 15:10:26 +00:00
|
|
|
|
|
|
|
export let xs = 12;
|
|
|
|
export let sm = xs;
|
|
|
|
export let md = sm;
|
|
|
|
export let lg = md;
|
|
|
|
export let xl = lg;
|
|
|
|
export let xxl = xl;
|
2023-11-17 00:05:35 +00:00
|
|
|
</script>
|
|
|
|
|
2024-08-31 15:10:26 +00:00
|
|
|
<Col {xs} {sm} {md} {lg} {xl} {xxl}>
|
2023-11-17 00:05:35 +00:00
|
|
|
<Card>
|
|
|
|
<CardHeader>
|
2023-11-17 02:15:23 +00:00
|
|
|
<CardTitle>{$_('section.status.title', { default: 'Status' })}</CardTitle>
|
2023-11-17 00:05:35 +00:00
|
|
|
</CardHeader>
|
|
|
|
<CardBody>
|
2023-11-19 19:27:22 +00:00
|
|
|
{#if $settings.screens}
|
2024-08-31 15:56:35 +00:00
|
|
|
<div class=" d-block d-sm-none mx-auto text-center">
|
|
|
|
{#each buttonChunks as chunk}
|
|
|
|
<ButtonGroup size="sm" class="mx-auto mb-1">
|
|
|
|
{#each chunk as s}
|
|
|
|
<Button
|
|
|
|
color="outline-primary"
|
|
|
|
active={$status.currentScreen == s.id}
|
|
|
|
on:click={setScreen(s.id)}>{s.name}</Button
|
|
|
|
>
|
|
|
|
{/each}
|
|
|
|
</ButtonGroup>
|
|
|
|
{/each}
|
|
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-center d-none d-sm-flex">
|
2023-11-19 19:27:22 +00:00
|
|
|
<ButtonGroup size="sm">
|
|
|
|
{#each $settings.screens as s}
|
|
|
|
<Button
|
|
|
|
color="outline-primary"
|
|
|
|
active={$status.currentScreen == s.id}
|
|
|
|
on:click={setScreen(s.id)}>{s.name}</Button
|
|
|
|
>
|
|
|
|
{/each}
|
|
|
|
</ButtonGroup>
|
|
|
|
</div>
|
2024-09-05 11:10:58 +00:00
|
|
|
{#if $settings.actCurrencies && $settings.ownDataSource}
|
2024-09-04 23:59:05 +00:00
|
|
|
<div class="d-flex justify-content-center d-none d-sm-flex mt-2">
|
|
|
|
<ButtonGroup size="sm">
|
|
|
|
{#each $settings.actCurrencies as c}
|
|
|
|
<Button
|
|
|
|
color="outline-success"
|
|
|
|
active={$status.currency == c}
|
|
|
|
on:click={setCurrency(c)}>{c}</Button
|
|
|
|
>
|
|
|
|
{/each}
|
|
|
|
</ButtonGroup>
|
|
|
|
</div>
|
|
|
|
{/if}
|
2023-11-19 19:27:22 +00:00
|
|
|
<hr />
|
|
|
|
{#if $status.data}
|
2024-08-31 15:10:26 +00:00
|
|
|
<section class={lightMode ? 'lightMode' : 'darkMode'}>
|
2024-08-31 15:18:26 +00:00
|
|
|
<Rendered status={$status} className="btclock-wrapper"></Rendered>
|
2023-11-19 19:27:22 +00:00
|
|
|
</section>
|
|
|
|
{$_('section.status.screenCycle')}:
|
|
|
|
<a
|
2023-11-24 23:42:37 +00:00
|
|
|
id="timerStatusText"
|
2023-11-19 19:27:22 +00:00
|
|
|
href={'#'}
|
|
|
|
style="cursor: pointer"
|
|
|
|
tabindex="0"
|
|
|
|
role="button"
|
|
|
|
aria-pressed="false"
|
|
|
|
on:click={toggleTimer($status.timerRunning)}
|
|
|
|
>{#if $status.timerRunning}⏵ {$_('timer.running')}{:else}⏸ {$_(
|
|
|
|
'timer.stopped'
|
|
|
|
)}{/if}</a
|
|
|
|
>
|
|
|
|
{/if}
|
|
|
|
{/if}
|
|
|
|
<hr />
|
2024-03-11 20:09:15 +00:00
|
|
|
{#if !$settings.disableLeds}
|
|
|
|
<Row class="justify-content-evenly">
|
|
|
|
{#if $status.leds}
|
|
|
|
{#each $status.leds as led}
|
|
|
|
<Col>
|
|
|
|
<Input
|
|
|
|
type="color"
|
|
|
|
id="ledColorPicker"
|
|
|
|
bind:value={led.hex}
|
|
|
|
class="mx-auto"
|
|
|
|
disabled
|
|
|
|
/>
|
|
|
|
</Col>
|
|
|
|
{/each}
|
|
|
|
{/if}
|
|
|
|
</Row>
|
|
|
|
<hr />
|
|
|
|
{/if}
|
2023-11-19 19:27:22 +00:00
|
|
|
<Progress striped value={memoryFreePercent}>{memoryFreePercent}%</Progress>
|
|
|
|
<div class="d-flex justify-content-between">
|
|
|
|
<div>{$_('section.status.memoryFree')}</div>
|
|
|
|
<div>
|
|
|
|
{Math.round($status.espFreeHeap / 1024)} / {Math.round($status.espHeapSize / 1024)} KiB
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<hr />
|
2024-06-29 00:12:29 +00:00
|
|
|
{#if $settings.hasLightLevel}
|
|
|
|
{$_('section.status.lightSensor')}: {Number(Math.round($status.lightLevel))} lux
|
|
|
|
<hr />
|
|
|
|
{/if}
|
2023-11-21 15:05:00 +00:00
|
|
|
<Progress striped id="rssiBar" color={wifiStrengthColor} value={rssiPercent}
|
|
|
|
>{rssiPercent}%</Progress
|
|
|
|
>
|
|
|
|
<Tooltip target="rssiBar" placement="bottom">{$_('rssiBar.tooltip')}</Tooltip>
|
|
|
|
|
|
|
|
<div class="d-flex justify-content-between">
|
|
|
|
<div>{$_('section.status.wifiSignalStrength')}</div>
|
|
|
|
<div>
|
|
|
|
{$status.rssi} dBm
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<hr />
|
2023-11-19 19:27:22 +00:00
|
|
|
{$_('section.status.uptime')}: {toUptimestring($status.espUptime)}
|
|
|
|
<br />
|
|
|
|
<p>
|
2024-08-31 13:37:20 +00:00
|
|
|
{#if $settings.useNostr || $settings.nostrZapNotify}
|
2024-07-15 13:11:44 +00:00
|
|
|
{$_('section.status.nostrConnection')}:
|
|
|
|
<span>
|
|
|
|
{#if $status.connectionStatus && $status.connectionStatus.nostr}
|
|
|
|
✅
|
|
|
|
{:else}
|
|
|
|
❌
|
|
|
|
{/if}
|
|
|
|
</span>
|
2024-08-31 13:37:20 +00:00
|
|
|
{/if}
|
|
|
|
{#if !$settings.useNostr}
|
|
|
|
{#if !$settings.ownDataSource}
|
|
|
|
{$_('section.status.wsPriceConnection')}:
|
|
|
|
<span>
|
2024-09-11 00:26:10 +00:00
|
|
|
{#if $status.connectionStatus && $status.connectionStatus.price}
|
2024-08-31 13:37:20 +00:00
|
|
|
✅
|
|
|
|
{:else}
|
|
|
|
❌
|
|
|
|
{/if}
|
|
|
|
</span>
|
|
|
|
-
|
|
|
|
{$_('section.status.wsMempoolConnection', {
|
|
|
|
values: { instance: $settings.mempoolInstance }
|
|
|
|
})}:
|
|
|
|
<span>
|
|
|
|
{#if $status.connectionStatus && $status.connectionStatus.blocks}
|
|
|
|
✅
|
|
|
|
{:else}
|
|
|
|
❌
|
|
|
|
{/if}
|
|
|
|
</span><br />
|
|
|
|
{:else}
|
|
|
|
{$_('section.status.wsDataConnection')}:
|
|
|
|
<span>
|
2024-09-05 11:10:58 +00:00
|
|
|
{#if $status.connectionStatus && $status.connectionStatus.V2}
|
2024-08-31 13:37:20 +00:00
|
|
|
✅
|
|
|
|
{:else}
|
|
|
|
❌
|
|
|
|
{/if}
|
|
|
|
</span>
|
|
|
|
{/if}
|
2024-05-08 22:54:55 +00:00
|
|
|
{/if}
|
2023-11-19 19:27:22 +00:00
|
|
|
{#if $settings.fetchEurPrice}
|
|
|
|
<small>{$_('section.status.fetchEuroNote')}</small>
|
|
|
|
{/if}
|
|
|
|
</p>
|
|
|
|
</CardBody>
|
|
|
|
</Card>
|
2023-11-17 00:05:35 +00:00
|
|
|
</Col>
|