mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-08-11 11:13:04 +02:00
Add airtime math and per-minute packets-over-uptime display for repeaters. Closes #194.
This commit is contained in:
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "remoteterm-meshcore-frontend",
|
"name": "remoteterm-meshcore-frontend",
|
||||||
"version": "3.11.0",
|
"version": "3.11.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "remoteterm-meshcore-frontend",
|
"name": "remoteterm-meshcore-frontend",
|
||||||
"version": "3.11.0",
|
"version": "3.11.3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/lang-python": "^6.2.1",
|
"@codemirror/lang-python": "^6.2.1",
|
||||||
"@codemirror/theme-one-dark": "^6.1.3",
|
"@codemirror/theme-one-dark": "^6.1.3",
|
||||||
|
|||||||
@@ -1,7 +1,23 @@
|
|||||||
|
import type { ReactNode } from 'react';
|
||||||
import { Separator } from '../ui/separator';
|
import { Separator } from '../ui/separator';
|
||||||
import { RepeaterPane, NotFetched, KvRow, formatDuration } from './repeaterPaneShared';
|
import { RepeaterPane, NotFetched, KvRow, formatDuration } from './repeaterPaneShared';
|
||||||
import type { RepeaterStatusResponse, PaneState } from '../../types';
|
import type { RepeaterStatusResponse, PaneState } from '../../types';
|
||||||
|
|
||||||
|
function Secondary({ children }: { children: ReactNode }) {
|
||||||
|
return <span className="ml-1.5 font-normal text-muted-foreground">{children}</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatAirtimePercent(airtimeSec: number, uptimeSec: number): string | null {
|
||||||
|
if (uptimeSec <= 0) return null;
|
||||||
|
return `${((airtimeSec / uptimeSec) * 100).toFixed(2)}%`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatPerMinute(count: number, uptimeSec: number): string | null {
|
||||||
|
if (uptimeSec <= 0) return null;
|
||||||
|
const rate = (count * 60) / uptimeSec;
|
||||||
|
return rate >= 10 ? rate.toFixed(0) : rate.toFixed(1);
|
||||||
|
}
|
||||||
|
|
||||||
export function TelemetryPane({
|
export function TelemetryPane({
|
||||||
data,
|
data,
|
||||||
state,
|
state,
|
||||||
@@ -13,6 +29,11 @@ export function TelemetryPane({
|
|||||||
onRefresh: () => void;
|
onRefresh: () => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}) {
|
}) {
|
||||||
|
const txPct = data ? formatAirtimePercent(data.airtime_seconds, data.uptime_seconds) : null;
|
||||||
|
const rxPct = data ? formatAirtimePercent(data.rx_airtime_seconds, data.uptime_seconds) : null;
|
||||||
|
const rxPerMin = data ? formatPerMinute(data.packets_received, data.uptime_seconds) : null;
|
||||||
|
const txPerMin = data ? formatPerMinute(data.packets_sent, data.uptime_seconds) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RepeaterPane title="Telemetry" state={state} onRefresh={onRefresh} disabled={disabled}>
|
<RepeaterPane title="Telemetry" state={state} onRefresh={onRefresh} disabled={disabled}>
|
||||||
{!data ? (
|
{!data ? (
|
||||||
@@ -21,8 +42,24 @@ export function TelemetryPane({
|
|||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<KvRow label="Battery" value={`${data.battery_volts.toFixed(3)}V`} />
|
<KvRow label="Battery" value={`${data.battery_volts.toFixed(3)}V`} />
|
||||||
<KvRow label="Uptime" value={formatDuration(data.uptime_seconds)} />
|
<KvRow label="Uptime" value={formatDuration(data.uptime_seconds)} />
|
||||||
<KvRow label="TX Airtime" value={formatDuration(data.airtime_seconds)} />
|
<KvRow
|
||||||
<KvRow label="RX Airtime" value={formatDuration(data.rx_airtime_seconds)} />
|
label="TX Airtime"
|
||||||
|
value={
|
||||||
|
<>
|
||||||
|
{formatDuration(data.airtime_seconds)}
|
||||||
|
{txPct && <Secondary>({txPct})</Secondary>}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<KvRow
|
||||||
|
label="RX Airtime"
|
||||||
|
value={
|
||||||
|
<>
|
||||||
|
{formatDuration(data.rx_airtime_seconds)}
|
||||||
|
{rxPct && <Secondary>({rxPct})</Secondary>}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<Separator className="my-1" />
|
<Separator className="my-1" />
|
||||||
<KvRow label="Noise Floor" value={`${data.noise_floor_dbm} dBm`} />
|
<KvRow label="Noise Floor" value={`${data.noise_floor_dbm} dBm`} />
|
||||||
<KvRow label="Last RSSI" value={`${data.last_rssi_dbm} dBm`} />
|
<KvRow label="Last RSSI" value={`${data.last_rssi_dbm} dBm`} />
|
||||||
@@ -30,7 +67,17 @@ export function TelemetryPane({
|
|||||||
<Separator className="my-1" />
|
<Separator className="my-1" />
|
||||||
<KvRow
|
<KvRow
|
||||||
label="Packets"
|
label="Packets"
|
||||||
value={`${data.packets_received.toLocaleString()} rx / ${data.packets_sent.toLocaleString()} tx`}
|
value={
|
||||||
|
<>
|
||||||
|
{data.packets_received.toLocaleString()} rx / {data.packets_sent.toLocaleString()}{' '}
|
||||||
|
tx
|
||||||
|
{rxPerMin && txPerMin && (
|
||||||
|
<Secondary>
|
||||||
|
(avg {rxPerMin} rx/min / {txPerMin} tx/min)
|
||||||
|
</Secondary>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<KvRow
|
<KvRow
|
||||||
label="Flood"
|
label="Flood"
|
||||||
|
|||||||
Reference in New Issue
Block a user