mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-09-26 14:07:58 +00:00
Simplify stock temporary radio test page
This commit is contained in:
@@ -902,7 +902,6 @@
|
||||
);
|
||||
|
||||
const staticCommands = setScheduledCommands();
|
||||
setCommand(root, "stock-cancel-during", staticCommands.stockCancelDuring);
|
||||
setCommand(root, "stock-leave-30", staticCommands.stockLeaveIn30);
|
||||
setCommand(root, "primary-cancel", staticCommands.primaryCancel);
|
||||
setCommand(root, "companion-cancel-before", staticCommands.companionCancelBefore);
|
||||
@@ -1057,19 +1056,27 @@
|
||||
root,
|
||||
"companion-now",
|
||||
phase === "before"
|
||||
? "Available one hour before the test — use Option 2 to schedule now."
|
||||
? "Available one hour before the test — schedule in advance below if supported."
|
||||
: endedMessage
|
||||
);
|
||||
}
|
||||
setCommand(
|
||||
root,
|
||||
"stock-cancel-during",
|
||||
immediateOpen ? commands.stockCancelDuring
|
||||
: phase === "before" ? "Available after you join the test." : "Test ended — no need to leave."
|
||||
);
|
||||
setCommandEnabled(root, "stock-now", immediateOpen);
|
||||
setCommandEnabled(root, "stock-cancel-during", immediateOpen);
|
||||
setCommandEnabled(root, "companion-now", immediateOpen);
|
||||
setMaterialCommandCopyEnabled(root, "stock-now", immediateOpen);
|
||||
setMaterialCommandCopyEnabled(root, "stock-cancel-during", immediateOpen);
|
||||
setMaterialCommandCopyEnabled(root, "companion-now", immediateOpen);
|
||||
setText(
|
||||
root,
|
||||
'[data-role="stock-now-note"]',
|
||||
phase === "before" && !immediateOpen
|
||||
? "Available one hour before the test; schedule it now with Option 2."
|
||||
? "The join command unlocks one hour before the test."
|
||||
: phase === "before"
|
||||
? "The setup window is open; the timeout includes the hour before the official start."
|
||||
: phase === "active"
|
||||
|
||||
@@ -139,6 +139,27 @@
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.preset-test-quick-command {
|
||||
border: 1px solid var(--preset-border);
|
||||
border-radius: 0.6rem;
|
||||
margin-top: 1rem;
|
||||
padding: 0.85rem 1rem 1rem;
|
||||
background: color-mix(in srgb, var(--preset-cyan) 5%, var(--md-default-bg-color));
|
||||
}
|
||||
|
||||
.preset-test-quick-command h3 {
|
||||
margin: 0 0 0.4rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.preset-test-quick-command .preset-test-note + .preset-test-note {
|
||||
margin-top: 0.4rem;
|
||||
}
|
||||
|
||||
.preset-test-stock-leave {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.preset-test-error {
|
||||
color: var(--md-code-hl-number-color);
|
||||
font-weight: 650;
|
||||
@@ -175,6 +196,8 @@
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.preset-test-quick-command pre,
|
||||
.preset-test-stock-leave pre,
|
||||
.preset-test-card pre,
|
||||
.preset-test > [data-role="content"] > section > pre {
|
||||
margin: 0.8rem 0;
|
||||
@@ -182,6 +205,8 @@
|
||||
border-radius: 0.35rem;
|
||||
}
|
||||
|
||||
.preset-test-quick-command pre code,
|
||||
.preset-test-stock-leave pre code,
|
||||
.preset-test-card pre code,
|
||||
.preset-test > [data-role="content"] > section > pre code {
|
||||
white-space: pre-wrap;
|
||||
@@ -348,6 +373,26 @@
|
||||
content: "Close generator";
|
||||
}
|
||||
|
||||
.preset-test-stock-leave > summary::after {
|
||||
content: "Show leave command";
|
||||
}
|
||||
|
||||
.preset-test-stock-leave[open] > summary::after {
|
||||
content: "Hide leave command";
|
||||
}
|
||||
|
||||
.preset-test-keymind-disclosure > summary::after {
|
||||
content: "Show advanced";
|
||||
}
|
||||
|
||||
.preset-test-keymind-disclosure {
|
||||
margin-top: 1.4rem;
|
||||
}
|
||||
|
||||
.preset-test-keymind-disclosure[open] > summary::after {
|
||||
content: "Hide advanced";
|
||||
}
|
||||
|
||||
.preset-test-generator-disclosure-body {
|
||||
padding: 0 1rem 1rem;
|
||||
}
|
||||
|
||||
+294
-290
@@ -3,8 +3,6 @@
|
||||
<span data-role="preset-test-page-summary">Choose a window and radio tuple to
|
||||
create a shareable temporary-radio test URL.</span>
|
||||
|
||||
Open a generated URL to see that test's status, instructions, and commands.
|
||||
|
||||
<div class="preset-test" data-preset-test>
|
||||
<div class="preset-test-error" data-role="config-error" role="alert" hidden></div>
|
||||
|
||||
@@ -25,6 +23,17 @@ Open a generated URL to see that test's status, instructions, and commands.
|
||||
<span class="preset-test-status" data-role="status" data-state="before">Scheduled</span>
|
||||
</div>
|
||||
|
||||
<div class="preset-test-quick-command" aria-labelledby="stock-test-title">
|
||||
<h3 id="stock-test-title">Stock firmware: copy this <code>tempradio</code> command</h3>
|
||||
<pre><code data-command="stock-now"></code></pre>
|
||||
<button type="button" data-copy-command="stock-now">Copy tempradio command</button>
|
||||
<p class="preset-test-note" data-role="stock-now-note"></p>
|
||||
<p class="preset-test-note">
|
||||
Before sending it, run <code>get radio</code> and save the result.
|
||||
No clock setup is needed. Your saved settings return automatically.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="preset-test-clock" aria-live="polite">
|
||||
<span class="preset-test-clock-label" data-role="countdown-label">Starts in</span>
|
||||
<strong data-role="countdown">—</strong>
|
||||
@@ -35,291 +44,17 @@ Open a generated URL to see that test's status, instructions, and commands.
|
||||
<div><dt>Start</dt><dd data-role="start-zoned"></dd></div>
|
||||
<div><dt>End</dt><dd data-role="end-zoned"></dd></div>
|
||||
<div><dt>Display time zone</dt><dd data-role="display-zone"></dd></div>
|
||||
<div><dt>Firmware epochs</dt><dd><code data-role="epoch-range"></code></dd></div>
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
<section class="preset-test-warning" aria-labelledby="continuity-plan-title">
|
||||
<h2 id="continuity-plan-title">Bridges and early-revert plan</h2>
|
||||
<p>
|
||||
The test will include bridges. If the Puget Sound area experiences a
|
||||
widespread power outage or loss of cellular service, we will end the
|
||||
test early. A stock node's one-minute temporary test profile then ends
|
||||
on that node's own saved radio settings.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="preset-test-warning" aria-labelledby="save-settings-title">
|
||||
<h2 id="save-settings-title">Before changing a radio</h2>
|
||||
<p>
|
||||
Run <code>get radio</code> and record the saved primary tuple. Both
|
||||
primary TempRadio methods return to that saved tuple; they do not store
|
||||
a return tuple inside the temporary command. On a Companion, also run
|
||||
<code>get radio2</code> and <code>get radio2.cross</code> so you can restore
|
||||
any non-default secondary-profile setup.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="clock-check-title">
|
||||
<h2 id="clock-check-title">Check the node clock before scheduling</h2>
|
||||
<p>
|
||||
The primary <code>tempradioat</code> and Companion
|
||||
<code>tempradioat2</code> schedulers use UTC Unix time. Run
|
||||
<code>clock</code> on every node that will be scheduled and compare it
|
||||
with the browser UTC time below. It should agree to within about a minute.
|
||||
A wrong clock can start late, start immediately, or cause the schedule to
|
||||
be rejected.
|
||||
</p>
|
||||
|
||||
<div class="preset-test-clock-check">
|
||||
<div>
|
||||
<span>Browser UTC now</span>
|
||||
<strong data-role="browser-utc">—</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Browser Unix time</span>
|
||||
<strong data-role="browser-epoch">—</strong>
|
||||
</div>
|
||||
<details class="preset-test-generator-disclosure preset-test-stock-leave">
|
||||
<summary><h2>Need to leave the test early?</h2></summary>
|
||||
<div class="preset-test-generator-disclosure-body">
|
||||
<p>Send this command to return to your saved radio settings in one minute:</p>
|
||||
<pre><code data-command="stock-cancel-during"></code></pre>
|
||||
<button type="button" data-copy-command="stock-cancel-during">Copy leave command</button>
|
||||
</div>
|
||||
|
||||
<div class="preset-test-clock-override">
|
||||
<label>
|
||||
<span>Node clock reported by <code>clock</code> (UTC, optional)</span>
|
||||
<input
|
||||
type="text"
|
||||
inputmode="text"
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
data-role="node-clock-input"
|
||||
placeholder="02:42 22/9/2026 UTC"
|
||||
>
|
||||
<small>
|
||||
Paste the node's <code>clock</code> reply immediately after it arrives.
|
||||
The firmware form <code>02:42 - 22/9/2026 UTC</code> is also accepted.
|
||||
Leave this blank to keep the normal UTC schedule epochs unchanged.
|
||||
</small>
|
||||
</label>
|
||||
<button type="button" data-action="apply-node-clock">Apply clock conversion</button>
|
||||
</div>
|
||||
<p class="preset-test-clock-status" data-role="node-clock-status" aria-live="polite">
|
||||
No node-clock correction is applied. Scheduled commands use the normal UTC epochs.
|
||||
</p>
|
||||
|
||||
<p class="preset-test-note">
|
||||
This changes only the absolute <code>tempradioat</code> and
|
||||
<code>tempradioat2</code> epochs shown on this page; it does not issue a
|
||||
clock-setting command. The correction is for this node and this open page
|
||||
only: it is never added to generated URLs, and is cleared on reload. If
|
||||
the node clock later syncs or jumps, delete and queue the schedule again.
|
||||
</p>
|
||||
|
||||
<div class="preset-test-grid preset-test-grid--clock">
|
||||
<article class="preset-test-card">
|
||||
<h3>Remote admin session</h3>
|
||||
<p>
|
||||
In a MeshCore client that supplies the sender timestamp, sync and
|
||||
then verify:
|
||||
</p>
|
||||
<pre><code>clock sync
|
||||
clock</code></pre>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card">
|
||||
<h3>Local USB or browser console</h3>
|
||||
<p>Copy this fresh, run it immediately, and then verify with <code>clock</code>:</p>
|
||||
<pre><code data-command="set-clock">time 0
|
||||
clock</code></pre>
|
||||
<button type="button" data-copy-command="set-clock">Copy current clock command</button>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card preset-test-card--wide">
|
||||
<h3>If the clock is ahead and cannot move backward</h3>
|
||||
<p>
|
||||
If setting the correct time returns <code>ERR: clock cannot go backwards</code>,
|
||||
run the command below. It resets the clock to an older fallback date and
|
||||
reboots the node immediately, so it sends no reply. After the node reconnects,
|
||||
copy and run the fresh local clock command above, verify with <code>clock</code>,
|
||||
and then add the Companion <code>tempradioat2</code> schedule again. The
|
||||
reboot clears any pending scheduled entries.
|
||||
</p>
|
||||
<p>
|
||||
If resetting or correcting this remote node's clock is not safe, leave
|
||||
it unchanged and use the optional node-clock conversion above instead.
|
||||
</p>
|
||||
<pre><code data-command="reset-clock">clkreboot</code></pre>
|
||||
<button type="button" data-copy-command="reset-clock">Copy clock reset command</button>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<p class="preset-test-note">
|
||||
The Companion schedule must be queued while both its start and end are
|
||||
in the future and within the firmware's roughly 24-day scheduling
|
||||
horizon. Scheduled entries are held in RAM and disappear if the node
|
||||
reboots.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="join-now-title">
|
||||
<h2 id="join-now-title">Option 1: switch during the setup window</h2>
|
||||
<p>
|
||||
The immediate commands become available one hour before the official
|
||||
start. Their timeout shrinks so every node still returns at the same end
|
||||
time. Before that setup window, the command text and copy controls stay
|
||||
unavailable.
|
||||
</p>
|
||||
|
||||
<div class="preset-test-grid">
|
||||
<article class="preset-test-card">
|
||||
<div class="preset-test-card-heading">
|
||||
<h3>Stock repeater, room server, or sensor</h3>
|
||||
<span>Primary radio</span>
|
||||
</div>
|
||||
<pre><code data-command="stock-now"></code></pre>
|
||||
<button type="button" data-copy-command="stock-now">Copy command</button>
|
||||
<p class="preset-test-note" data-role="stock-now-note"></p>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card">
|
||||
<div class="preset-test-card-heading">
|
||||
<h3>Companion using both frequencies</h3>
|
||||
<span>Dual profile</span>
|
||||
</div>
|
||||
<pre><code data-command="companion-now"></code></pre>
|
||||
<button type="button" data-copy-command="companion-now">Copy commands</button>
|
||||
<p class="preset-test-note">
|
||||
<code>rxtx</code> permits transmission on the second profile;
|
||||
<code>radio2.cross on</code> copies ordinary Companion traffic across
|
||||
the primary and temporary profiles.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="schedule-title">
|
||||
<h2 id="schedule-title">Option 2: schedule a supported node in advance</h2>
|
||||
<p>
|
||||
A Simple Repeater build can schedule its primary radio with
|
||||
<code>tempradioat</code>. A Companion can instead schedule its second
|
||||
profile with <code>tempradioat2</code>. Both commands use the exact UTC
|
||||
epochs below, switch at the common start, and restore saved settings at
|
||||
the common end. A node-clock conversion above replaces only those command
|
||||
epochs with its per-node translated values. Room-server and sensor roles
|
||||
use Option 1 instead.
|
||||
</p>
|
||||
|
||||
<div class="preset-test-grid">
|
||||
<article class="preset-test-card">
|
||||
<div class="preset-test-card-heading">
|
||||
<h3>Room server or sensor</h3>
|
||||
<span>No advance schedule</span>
|
||||
</div>
|
||||
<p class="preset-test-note">
|
||||
Use the immediate <code>tempradio</code> command in Option 1 after
|
||||
its setup window opens.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card">
|
||||
<div class="preset-test-card-heading">
|
||||
<h3>Simple Repeater primary radio</h3>
|
||||
<span>Primary schedule</span>
|
||||
</div>
|
||||
<pre><code data-command="primary-scheduled"></code></pre>
|
||||
<button type="button" data-copy-command="primary-scheduled">Copy schedule commands</button>
|
||||
<p class="preset-test-note">
|
||||
This is available only on a Simple Repeater build with primary
|
||||
scheduled-radio support. It changes the primary tuple at the start
|
||||
and restores the saved tuple at the end. If <code>get tempradioat</code>
|
||||
returns <code>Error: unsupported</code>, use Option 1 instead.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card">
|
||||
<div class="preset-test-card-heading">
|
||||
<h3>Companion using both frequencies</h3>
|
||||
<span>Dual-profile schedule</span>
|
||||
</div>
|
||||
<pre><code data-command="companion-scheduled"></code></pre>
|
||||
<button type="button" data-copy-command="companion-scheduled">Copy schedule commands</button>
|
||||
<p class="preset-test-note">
|
||||
Crossing is saved independently and remains <code>on</code> after the
|
||||
temporary second profile ends. Restore its previous value after the
|
||||
test; <code>auto</code> is the normal default.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="cancel-title">
|
||||
<h2 id="cancel-title">Cancel or leave the test</h2>
|
||||
<p>
|
||||
A stock node can leave an active test as shown below. For a primary or
|
||||
Companion schedule, the <code>all</code> form removes every temporary
|
||||
schedule in that family. To preserve another schedule, first run the
|
||||
corresponding <code>get</code> command and replace <code>all</code> with
|
||||
its displayed entry number.
|
||||
</p>
|
||||
|
||||
<div class="preset-test-cancel-grid">
|
||||
<article class="preset-test-card">
|
||||
<h3>Stock · while it is running</h3>
|
||||
<h4>Leave now · stock compatible</h4>
|
||||
<pre><code data-command="stock-cancel-during"></code></pre>
|
||||
<button type="button" data-copy-command="stock-cancel-during">Copy stock leave command</button>
|
||||
<p class="preset-test-note">
|
||||
Stock MeshCore has no <code>normalradio</code> command. This starts a
|
||||
one-minute temporary session on this page's test profile without
|
||||
saving over the node's configuration. When that minute ends, the node
|
||||
restores whatever primary radio settings it had saved.
|
||||
</p>
|
||||
<h4>Leave in 30 minutes</h4>
|
||||
<pre><code data-command="stock-leave-30"></code></pre>
|
||||
<button type="button" data-copy-command="stock-leave-30">Copy 30-minute command</button>
|
||||
<p class="preset-test-note">
|
||||
This replaces the current temporary timeout with 30 minutes, then
|
||||
restores the saved primary tuple automatically.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card">
|
||||
<h3>Simple Repeater · scheduled primary radio</h3>
|
||||
<pre><code data-command="primary-cancel"></code></pre>
|
||||
<button type="button" data-copy-command="primary-cancel">Copy cancel commands</button>
|
||||
<p class="preset-test-note">
|
||||
Before the start, this removes the queued temporary schedule. While
|
||||
it is running, it also restores the saved primary tuple after the
|
||||
command reply drains.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card">
|
||||
<h3>Companion · before it starts</h3>
|
||||
<pre><code data-command="companion-cancel-before"></code></pre>
|
||||
<button type="button" data-copy-command="companion-cancel-before">Copy cancel commands</button>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card">
|
||||
<h3>Companion · while it is running</h3>
|
||||
<h4>Leave now</h4>
|
||||
<pre><code data-command="companion-cancel-during"></code></pre>
|
||||
<button type="button" data-copy-command="companion-cancel-during">Copy restore commands</button>
|
||||
<p class="preset-test-note">
|
||||
If <code>get radio2.cross</code> was not <code>auto</code> before the
|
||||
test, restore that recorded value instead.
|
||||
</p>
|
||||
<h4>Leave in 30 minutes</h4>
|
||||
<pre><code data-command="companion-leave-30"></code></pre>
|
||||
<button type="button" data-copy-command="companion-leave-30">Copy 30-minute commands</button>
|
||||
<p class="preset-test-note">
|
||||
These commands clear any absolute second-profile schedule and give
|
||||
the test profile a fresh 30-minute lease. The saved second profile
|
||||
returns at expiry, but crossing remains <code>on</code>; afterward,
|
||||
restore the value you recorded before the test (<code>auto</code> is
|
||||
the normal default).
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
</details>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -449,15 +184,284 @@ clock</code></pre>
|
||||
</section>
|
||||
|
||||
<div data-role="test-content-footer" hidden>
|
||||
<details class="preset-test-generator-disclosure preset-test-keymind-disclosure"
|
||||
data-role="keymind-disclosure">
|
||||
<summary><h2>KeyMind firmware and advanced commands</h2></summary>
|
||||
<div class="preset-test-generator-disclosure-body">
|
||||
<p>
|
||||
Primary <code>tempradioat</code> scheduling is implemented by the Simple
|
||||
Repeater role; room-server and sensor roles use their immediate
|
||||
<code>tempradio</code> command during the setup window. The Companion
|
||||
scheduling commands require current full-parser firmware, and
|
||||
<code>tempradio2</code> and <code>tempradioat2</code> require a build with
|
||||
dual-radio-profile support. If a node reports an unknown command, use only
|
||||
a method that its installed firmware documents.
|
||||
Use these only if your firmware supports the listed commands or you need
|
||||
dual-radio operation, scheduling, or clock correction.
|
||||
</p>
|
||||
<p>Firmware schedule epochs: <code data-role="epoch-range"></code></p>
|
||||
|
||||
<section class="preset-test-warning" aria-labelledby="continuity-plan-title">
|
||||
<h2 id="continuity-plan-title">Bridges and early-revert plan</h2>
|
||||
<p>
|
||||
The test will include bridges. If the Puget Sound area experiences a
|
||||
widespread power outage or loss of cellular service, we will end the
|
||||
test early. A stock node's one-minute temporary test profile then ends
|
||||
on that node's own saved radio settings.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="preset-test-warning" aria-labelledby="save-settings-title">
|
||||
<h2 id="save-settings-title">Before changing a radio</h2>
|
||||
<p>
|
||||
Run <code>get radio</code> and record the saved primary tuple. Both
|
||||
primary TempRadio methods return to that saved tuple; they do not store
|
||||
a return tuple inside the temporary command. On a Companion, also run
|
||||
<code>get radio2</code> and <code>get radio2.cross</code> so you can restore
|
||||
any non-default secondary-profile setup.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="clock-check-title">
|
||||
<h2 id="clock-check-title">Check the node clock before scheduling</h2>
|
||||
<p>
|
||||
The primary <code>tempradioat</code> and Companion
|
||||
<code>tempradioat2</code> schedulers use UTC Unix time. Run
|
||||
<code>clock</code> on every node that will be scheduled and compare it
|
||||
with the browser UTC time below. It should agree to within about a minute.
|
||||
A wrong clock can start late, start immediately, or cause the schedule to
|
||||
be rejected.
|
||||
</p>
|
||||
|
||||
<div class="preset-test-clock-check">
|
||||
<div>
|
||||
<span>Browser UTC now</span>
|
||||
<strong data-role="browser-utc">—</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Browser Unix time</span>
|
||||
<strong data-role="browser-epoch">—</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="preset-test-clock-override">
|
||||
<label>
|
||||
<span>Node clock reported by <code>clock</code> (UTC, optional)</span>
|
||||
<input
|
||||
type="text"
|
||||
inputmode="text"
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
data-role="node-clock-input"
|
||||
placeholder="02:42 22/9/2026 UTC"
|
||||
>
|
||||
<small>
|
||||
Paste the node's <code>clock</code> reply immediately after it arrives.
|
||||
The firmware form <code>02:42 - 22/9/2026 UTC</code> is also accepted.
|
||||
Leave this blank to keep the normal UTC schedule epochs unchanged.
|
||||
</small>
|
||||
</label>
|
||||
<button type="button" data-action="apply-node-clock">Apply clock conversion</button>
|
||||
</div>
|
||||
<p class="preset-test-clock-status" data-role="node-clock-status" aria-live="polite">
|
||||
No node-clock correction is applied. Scheduled commands use the normal UTC epochs.
|
||||
</p>
|
||||
|
||||
<p class="preset-test-note">
|
||||
This changes only the absolute <code>tempradioat</code> and
|
||||
<code>tempradioat2</code> epochs shown on this page; it does not issue a
|
||||
clock-setting command. The correction is for this node and this open page
|
||||
only: it is never added to generated URLs, and is cleared on reload. If
|
||||
the node clock later syncs or jumps, delete and queue the schedule again.
|
||||
</p>
|
||||
|
||||
<div class="preset-test-grid preset-test-grid--clock">
|
||||
<article class="preset-test-card">
|
||||
<h3>Remote admin session</h3>
|
||||
<p>
|
||||
In a MeshCore client that supplies the sender timestamp, sync and
|
||||
then verify:
|
||||
</p>
|
||||
<pre><code>clock sync
|
||||
clock</code></pre>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card">
|
||||
<h3>Local USB or browser console</h3>
|
||||
<p>Copy this fresh, run it immediately, and then verify with <code>clock</code>:</p>
|
||||
<pre><code data-command="set-clock">time 0
|
||||
clock</code></pre>
|
||||
<button type="button" data-copy-command="set-clock">Copy current clock command</button>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card preset-test-card--wide">
|
||||
<h3>If the clock is ahead and cannot move backward</h3>
|
||||
<p>
|
||||
If setting the correct time returns <code>ERR: clock cannot go backwards</code>,
|
||||
run the command below. It resets the clock to an older fallback date and
|
||||
reboots the node immediately, so it sends no reply. After the node reconnects,
|
||||
copy and run the fresh local clock command above, verify with <code>clock</code>,
|
||||
and then add the Companion <code>tempradioat2</code> schedule again. The
|
||||
reboot clears any pending scheduled entries.
|
||||
</p>
|
||||
<p>
|
||||
If resetting or correcting this remote node's clock is not safe, leave
|
||||
it unchanged and use the optional node-clock conversion above instead.
|
||||
</p>
|
||||
<pre><code data-command="reset-clock">clkreboot</code></pre>
|
||||
<button type="button" data-copy-command="reset-clock">Copy clock reset command</button>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<p class="preset-test-note">
|
||||
The Companion schedule must be queued while both its start and end are
|
||||
in the future and within the firmware's roughly 24-day scheduling
|
||||
horizon. Scheduled entries are held in RAM and disappear if the node
|
||||
reboots.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="join-now-title">
|
||||
<h2 id="join-now-title">Companion: use both frequencies</h2>
|
||||
<p>
|
||||
These commands become available one hour before the official start.
|
||||
Their timeout shrinks so the Companion returns at the same end time.
|
||||
</p>
|
||||
|
||||
<div class="preset-test-grid">
|
||||
<article class="preset-test-card">
|
||||
<div class="preset-test-card-heading">
|
||||
<h3>Companion using both frequencies</h3>
|
||||
<span>Dual profile</span>
|
||||
</div>
|
||||
<pre><code data-command="companion-now"></code></pre>
|
||||
<button type="button" data-copy-command="companion-now">Copy commands</button>
|
||||
<p class="preset-test-note">
|
||||
<code>rxtx</code> permits transmission on the second profile;
|
||||
<code>radio2.cross on</code> copies ordinary Companion traffic across
|
||||
the primary and temporary profiles.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="schedule-title">
|
||||
<h2 id="schedule-title">Schedule a supported node in advance</h2>
|
||||
<p>
|
||||
A Simple Repeater build can schedule its primary radio with
|
||||
<code>tempradioat</code>. A Companion can instead schedule its second
|
||||
profile with <code>tempradioat2</code>. Both commands use the exact UTC
|
||||
epochs below, switch at the common start, and restore saved settings at
|
||||
the common end. A node-clock conversion above replaces only those command
|
||||
epochs with its per-node translated values. Room-server and sensor roles
|
||||
use the stock join command above instead.
|
||||
</p>
|
||||
|
||||
<div class="preset-test-grid">
|
||||
<article class="preset-test-card">
|
||||
<div class="preset-test-card-heading">
|
||||
<h3>Room server or sensor</h3>
|
||||
<span>No advance schedule</span>
|
||||
</div>
|
||||
<p class="preset-test-note">
|
||||
Use the stock <code>tempradio</code> command above after
|
||||
its setup window opens.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card">
|
||||
<div class="preset-test-card-heading">
|
||||
<h3>Simple Repeater primary radio</h3>
|
||||
<span>Primary schedule</span>
|
||||
</div>
|
||||
<pre><code data-command="primary-scheduled"></code></pre>
|
||||
<button type="button" data-copy-command="primary-scheduled">Copy schedule commands</button>
|
||||
<p class="preset-test-note">
|
||||
This is available only on a Simple Repeater build with primary
|
||||
scheduled-radio support. It changes the primary tuple at the start
|
||||
and restores the saved tuple at the end. If <code>get tempradioat</code>
|
||||
returns <code>Error: unsupported</code>, use the stock join command
|
||||
above instead.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card">
|
||||
<div class="preset-test-card-heading">
|
||||
<h3>Companion using both frequencies</h3>
|
||||
<span>Dual-profile schedule</span>
|
||||
</div>
|
||||
<pre><code data-command="companion-scheduled"></code></pre>
|
||||
<button type="button" data-copy-command="companion-scheduled">Copy schedule commands</button>
|
||||
<p class="preset-test-note">
|
||||
Crossing is saved independently and remains <code>on</code> after the
|
||||
temporary second profile ends. Restore its previous value after the
|
||||
test; <code>auto</code> is the normal default.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="cancel-title">
|
||||
<h2 id="cancel-title">Cancel a schedule or adjust the timeout</h2>
|
||||
<p>
|
||||
For a primary or Companion schedule, the <code>all</code> form removes every temporary
|
||||
schedule in that family. To preserve another schedule, first run the
|
||||
corresponding <code>get</code> command and replace <code>all</code> with
|
||||
its displayed entry number.
|
||||
</p>
|
||||
|
||||
<div class="preset-test-cancel-grid">
|
||||
<article class="preset-test-card">
|
||||
<h3>Stock: leave in 30 minutes</h3>
|
||||
<pre><code data-command="stock-leave-30"></code></pre>
|
||||
<button type="button" data-copy-command="stock-leave-30">Copy 30-minute command</button>
|
||||
<p class="preset-test-note">
|
||||
This replaces the current temporary timeout with 30 minutes, then
|
||||
restores the saved primary tuple automatically.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card">
|
||||
<h3>Simple Repeater · scheduled primary radio</h3>
|
||||
<pre><code data-command="primary-cancel"></code></pre>
|
||||
<button type="button" data-copy-command="primary-cancel">Copy cancel commands</button>
|
||||
<p class="preset-test-note">
|
||||
Before the start, this removes the queued temporary schedule. While
|
||||
it is running, it also restores the saved primary tuple after the
|
||||
command reply drains.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card">
|
||||
<h3>Companion · before it starts</h3>
|
||||
<pre><code data-command="companion-cancel-before"></code></pre>
|
||||
<button type="button" data-copy-command="companion-cancel-before">Copy cancel commands</button>
|
||||
</article>
|
||||
|
||||
<article class="preset-test-card">
|
||||
<h3>Companion · while it is running</h3>
|
||||
<h4>Leave now</h4>
|
||||
<pre><code data-command="companion-cancel-during"></code></pre>
|
||||
<button type="button" data-copy-command="companion-cancel-during">Copy restore commands</button>
|
||||
<p class="preset-test-note">
|
||||
If <code>get radio2.cross</code> was not <code>auto</code> before the
|
||||
test, restore that recorded value instead.
|
||||
</p>
|
||||
<h4>Leave in 30 minutes</h4>
|
||||
<pre><code data-command="companion-leave-30"></code></pre>
|
||||
<button type="button" data-copy-command="companion-leave-30">Copy 30-minute commands</button>
|
||||
<p class="preset-test-note">
|
||||
These commands clear any absolute second-profile schedule and give
|
||||
the test profile a fresh 30-minute lease. The saved second profile
|
||||
returns at expiry, but crossing remains <code>on</code>; afterward,
|
||||
restore the value you recorded before the test (<code>auto</code> is
|
||||
the normal default).
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<p class="preset-test-note">
|
||||
Primary scheduling requires a Simple Repeater build. Companion
|
||||
<code>tempradio2</code> and <code>tempradioat2</code> require dual-profile
|
||||
firmware. If a command is unknown, use only the method your installed
|
||||
firmware supports.
|
||||
</p>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@ extra_css:
|
||||
- _stylesheets/telemetry_decoder.css
|
||||
- _stylesheets/management_decoder.css
|
||||
- _stylesheets/filter_tool.css
|
||||
- _stylesheets/preset_test.css?v=20260921-1
|
||||
- _stylesheets/preset_test.css?v=20260922-1
|
||||
|
||||
extra_javascript:
|
||||
- https://unpkg.com/leaflet@1.9.4/dist/leaflet.js
|
||||
@@ -30,4 +30,4 @@ extra_javascript:
|
||||
- _javascript/telemetry_decoder.js
|
||||
- _javascript/management_decoder.js
|
||||
- _javascript/filter_tool.js
|
||||
- _javascript/preset_test.js?v=20260921-3
|
||||
- _javascript/preset_test.js?v=20260922-1
|
||||
|
||||
@@ -14,6 +14,38 @@ assert.doesNotMatch(pageSource, /<select name="tz"/);
|
||||
assert.match(pageSource, /data-role="test-content" hidden/);
|
||||
assert.match(pageSource, /data-role="test-content-footer" hidden/);
|
||||
assert.match(pageSource, /data-role="url-builder-disclosure" open/);
|
||||
assert.match(pageSource, /class="preset-test-quick-command"/);
|
||||
assert.match(pageSource, /class="preset-test-generator-disclosure preset-test-stock-leave"/);
|
||||
assert.match(pageSource, /data-role="keymind-disclosure"/);
|
||||
assert.match(pageSource, /<details class="preset-test-generator-disclosure preset-test-keymind-disclosure"\s+data-role="keymind-disclosure">/);
|
||||
const keymindStart = pageSource.indexOf('data-role="keymind-disclosure"');
|
||||
const keymindEnd = pageSource.indexOf("</details>", keymindStart);
|
||||
const keymindContent = pageSource.slice(keymindStart, keymindEnd);
|
||||
assert(pageSource.indexOf('id="stock-test-title"') < keymindStart);
|
||||
assert(pageSource.indexOf('data-command="stock-now"') <
|
||||
pageSource.indexOf('data-role="countdown"'));
|
||||
assert(pageSource.indexOf('data-command="stock-now"') <
|
||||
pageSource.indexOf('data-role="url-builder-disclosure"'));
|
||||
assert(pageSource.indexOf('data-role="url-builder-disclosure"') <
|
||||
pageSource.indexOf('data-role="test-content-footer"'));
|
||||
assert(pageSource.indexOf('data-role="test-content-footer"') < keymindStart);
|
||||
assert.strictEqual((pageSource.match(/data-command="stock-now"/g) || []).length, 1);
|
||||
assert.strictEqual((pageSource.match(/data-command="stock-cancel-during"/g) || []).length, 1);
|
||||
assert.doesNotMatch(keymindContent, /data-command="stock-now"/);
|
||||
for (const name of ["set-clock", "reset-clock", "companion-now", "primary-scheduled",
|
||||
"companion-scheduled", "primary-cancel", "companion-cancel-before",
|
||||
"companion-cancel-during"]) {
|
||||
assert.match(keymindContent, new RegExp('data-command="' + name + '"'));
|
||||
}
|
||||
const openTags = [];
|
||||
for (const match of pageSource.matchAll(/<\/?(div|details|section|article|summary)\b[^>]*>/g)) {
|
||||
if (match[0][1] === "/") {
|
||||
assert.strictEqual(openTags.pop(), match[1], "nested page HTML must stay balanced");
|
||||
} else {
|
||||
openTags.push(match[1]);
|
||||
}
|
||||
}
|
||||
assert.deepStrictEqual(openTags, []);
|
||||
assert.match(pageSource, /data-role="node-clock-input"/);
|
||||
assert.match(pageSource, /placeholder="02:42 22\/9\/2026 UTC"/);
|
||||
assert.match(pageSource, /data-action="apply-node-clock"/);
|
||||
@@ -98,6 +130,10 @@ assert.strictEqual(tool.presetPageTitle(requestedLink), "Temporary radio test ·
|
||||
assert.match(tool.presetPageSummary(requestedLink), /911\.3 MHz, 500 kHz, SF8, CR7, 22 dBm/);
|
||||
assert.doesNotMatch(tool.presetPageSummary(requestedLink), /910\.1 MHz/);
|
||||
assert.strictEqual(tool.presetEyebrow(requestedLink), "MeshCore · 48-hour temporary preset test");
|
||||
assert.strictEqual(
|
||||
tool.commandsFor(requestedLink, requestedLink.startMs).stockNow,
|
||||
"tempradio 911.3,500,8,7,2880"
|
||||
);
|
||||
assert.strictEqual(
|
||||
tool.commandsFor(requestedLink, requestedLink.startMs).primaryScheduled,
|
||||
"set tempradioat 911.3,500,8,7,1790035200,1790208000\nget tempradioat"
|
||||
|
||||
Reference in New Issue
Block a user