Use stock-compatible radio test exit

This commit is contained in:
mikecarper committed 2026-09-16 14:58:38 -07:00
1 parent d61b287ddc
commit 2cd9a9dbae
4 files changed
+132 -7

No files matched your search

+55 -1
View File
@@ -9,6 +9,10 @@
bw: "500",
sf: "8",
cr: "7",
normalfreq: "910.525",
normalbw: "62.5",
normalsf: "7",
normalcr: "5",
tx: "22",
});
const VALID_BANDWIDTHS = Object.freeze([
@@ -108,6 +112,10 @@
const bw = strictNumber(raw.bw, "bw");
const sf = strictInteger(raw.sf, "sf");
const cr = strictInteger(raw.cr, "cr");
const normalFreq = strictNumber(raw.normalfreq, "normalfreq");
const normalBw = strictNumber(raw.normalbw, "normalbw");
const normalSf = strictInteger(raw.normalsf, "normalsf");
const normalCr = strictInteger(raw.normalcr, "normalcr");
const tx = strictSignedNumber(raw.tx, "tx");
if (endMs <= startMs) {
@@ -129,6 +137,22 @@
if (cr < 5 || cr > 8) {
throw new PresetTestError("cr must be between 5 and 8");
}
if (normalFreq < 150 || normalFreq > 2500) {
throw new PresetTestError("normalfreq must be between 150 and 2500 MHz");
}
if (!VALID_BANDWIDTHS.some(function (allowed) {
return Math.abs(allowed - normalBw) < 0.01;
})) {
throw new PresetTestError(
"normalbw must be one of " + VALID_BANDWIDTHS.join(", ") + " kHz"
);
}
if (normalSf < 5 || normalSf > 12) {
throw new PresetTestError("normalsf must be between 5 and 12");
}
if (normalCr < 5 || normalCr > 8) {
throw new PresetTestError("normalcr must be between 5 and 8");
}
if (tx < -30 || tx > 60) {
throw new PresetTestError("tx must be between -30 and 60 dBm");
}
@@ -143,9 +167,15 @@
bw: bw,
sf: sf,
cr: cr,
normalFreq: normalFreq,
normalBw: normalBw,
normalSf: normalSf,
normalCr: normalCr,
tx: tx,
freqText: numberText(freq),
bwText: numberText(bw),
normalFreqText: numberText(normalFreq),
normalBwText: numberText(normalBw),
txText: numberText(tx),
});
}
@@ -179,6 +209,9 @@
function commandsFor(config, nowMs) {
const tuple = [config.freqText, config.bwText, config.sf, config.cr].join(",");
const normalTuple = [
config.normalFreqText, config.normalBwText, config.normalSf, config.normalCr,
].join(",");
const minutes = remainingMinutes(config, nowMs);
return Object.freeze({
stockNow: "tempradio " + tuple + "," + minutes,
@@ -191,7 +224,7 @@
"set radio2.cross on\nset tempradioat2 " + tuple + ",rxtx," +
config.startEpoch + "," + config.endEpoch + "\nget tempradioat2",
stockCancelBefore: "get tempradioat\ndel tempradioat all",
stockCancelDuring: "normalradio",
stockCancelDuring: "tempradio " + normalTuple + ",1",
stockLeaveIn30: "tempradio " + tuple + ",30",
companionCancelBefore:
"get tempradioat2\ndel tempradioat2 all\nset radio2.cross auto",
@@ -369,6 +402,10 @@
params.set("bw", values.bw);
params.set("sf", values.sf);
params.set("cr", values.cr);
params.set("normalfreq", values.normalfreq);
params.set("normalbw", values.normalbw);
params.set("normalsf", values.normalsf);
params.set("normalcr", values.normalcr);
params.set("tx", values.tx);
return configFromSearch("?" + params.toString());
}
@@ -397,6 +434,10 @@
url.searchParams.set("bw", config.bwText);
url.searchParams.set("sf", String(config.sf));
url.searchParams.set("cr", String(config.cr));
url.searchParams.set("normalfreq", config.normalFreqText);
url.searchParams.set("normalbw", config.normalBwText);
url.searchParams.set("normalsf", String(config.normalSf));
url.searchParams.set("normalcr", String(config.normalCr));
url.searchParams.set("tx", config.txText);
return url.toString();
}
@@ -472,6 +513,11 @@
setText(root, '[data-field="bw-display"]', config.bwText);
setText(root, '[data-field="sf"]', String(config.sf));
setText(root, '[data-field="cr"]', String(config.cr));
setText(
root,
'[data-field="normal-profile"]',
[config.normalFreqText, config.normalBwText, config.normalSf, config.normalCr].join(",")
);
setText(root, '[data-role="start-zoned"]', formatZoned(config.startMs, config.tz));
setText(root, '[data-role="end-zoned"]', formatZoned(config.endMs, config.tz));
setText(root, '[data-role="display-zone"]', config.tz);
@@ -507,6 +553,10 @@
generator.elements.bw.value = config.bwText;
generator.elements.sf.value = String(config.sf);
generator.elements.cr.value = String(config.cr);
generator.elements.normalfreq.value = config.normalFreqText;
generator.elements.normalbw.value = config.normalBwText;
generator.elements.normalsf.value = String(config.normalSf);
generator.elements.normalcr.value = String(config.normalCr);
generator.elements.tx.value = config.txText;
const zoneList = root.querySelector("#preset-test-time-zones");
@@ -531,6 +581,10 @@
bw: generator.elements.bw.value,
sf: generator.elements.sf.value,
cr: generator.elements.cr.value,
normalfreq: generator.elements.normalfreq.value,
normalbw: generator.elements.normalbw.value,
normalsf: generator.elements.normalsf.value,
normalcr: generator.elements.normalcr.value,
tx: generator.elements.tx.value,
});
const url = configuredUrl(
+11
View File
@@ -278,6 +278,17 @@
font-weight: 700;
}
.preset-test-generator-subheading {
grid-column: 1 / -1;
border-bottom: 1px solid var(--preset-border);
padding: 0.3rem 0 0.35rem;
color: var(--preset-cyan);
font-size: 0.74rem;
font-weight: 800;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.preset-test-generator input,
.preset-test-generator select {
box-sizing: border-box;
+38 -6
View File
@@ -47,7 +47,8 @@ tuple; no source edit is required.
<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 and revert to the normal 910.525 MHz channel.
test early and revert to the normal
<code data-field="normal-profile">910.525,62.5,7,5</code> profile.
</p>
</section>
@@ -212,12 +213,14 @@ clock</code></pre>
<article class="preset-test-card">
<h3>Stock · while it is running</h3>
<h4>Leave now</h4>
<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 restore command</button>
<button type="button" data-copy-command="stock-cancel-during">Copy stock leave command</button>
<p class="preset-test-note">
<code>normalradio</code> cancels pending and active primary TempRadio
windows and restores the saved primary tuple after its reply drains.
Stock MeshCore has no <code>normalradio</code> command. This starts a
one-minute temporary session on the normal return profile without
saving over the node's configuration. When that minute ends, the
node restores its saved radio settings.
</p>
<h4>Leave in 30 minutes</h4>
<pre><code data-command="stock-leave-30"></code></pre>
@@ -283,6 +286,7 @@ clock</code></pre>
autocomplete="off" spellcheck="false">
<small>Use an IANA name such as America/Los_Angeles or UTC.</small>
</label>
<div class="preset-test-generator-subheading">Test radio profile</div>
<label>
<span>Frequency (MHz)</span>
<input type="number" name="freq" min="150" max="2500" step="0.001" required>
@@ -313,6 +317,32 @@ clock</code></pre>
<input type="number" name="tx" min="-30" max="60" step="0.1" required>
<small>This estimate-only value does not change the TempRadio commands.</small>
</label>
<div class="preset-test-generator-subheading">Normal return profile</div>
<label>
<span>Normal frequency (MHz)</span>
<input type="number" name="normalfreq" min="150" max="2500" step="0.001" required>
</label>
<label>
<span>Normal bandwidth (kHz)</span>
<select name="normalbw" required>
<option>7.8</option><option>10.4</option><option>15.6</option>
<option>20.8</option><option>31.25</option><option>41.7</option>
<option>62.5</option><option>125</option><option>250</option><option>500</option>
</select>
</label>
<label>
<span>Normal spreading factor</span>
<select name="normalsf" required>
<option>5</option><option>6</option><option>7</option><option>8</option>
<option>9</option><option>10</option><option>11</option><option>12</option>
</select>
</label>
<label>
<span>Normal coding-rate denominator</span>
<select name="normalcr" required>
<option>5</option><option>6</option><option>7</option><option>8</option>
</select>
</label>
</div>
<button type="submit">Generate test URL</button>
</form>
@@ -361,7 +391,9 @@ clock</code></pre>
Advanced use: <code>start</code> and <code>end</code> also accept ISO-8601
timestamps with explicit UTC offsets or Unix epoch seconds. The other URL
parameters are <code>tz</code>, <code>freq</code>, <code>bw</code>,
<code>sf</code>, <code>cr</code>, and estimate-only <code>tx</code>.
<code>sf</code>, <code>cr</code>, <code>normalfreq</code>,
<code>normalbw</code>, <code>normalsf</code>, <code>normalcr</code>, and
estimate-only <code>tx</code>.
</p>
</section>
</div>
+28
View File
@@ -18,6 +18,10 @@ assert.strictEqual(config.sf, 8);
assert.strictEqual(config.cr, 7);
assert.strictEqual(config.tz, "America/Los_Angeles");
assert.strictEqual(config.tx, 22);
assert.strictEqual(config.normalFreq, 910.525);
assert.strictEqual(config.normalBw, 62.5);
assert.strictEqual(config.normalSf, 7);
assert.strictEqual(config.normalCr, 5);
assert.strictEqual(defaults.startEpoch, config.startEpoch);
assert.strictEqual(defaults.endEpoch, config.endEpoch);
assert.strictEqual(defaults.freq, config.freq);
@@ -58,6 +62,10 @@ assert.strictEqual(
"get tempradioat2"
);
assert.strictEqual(commands.stockLeaveIn30, "tempradio 910.1,500,8,7,30");
assert.strictEqual(
commands.stockCancelDuring,
"tempradio 910.525,62.5,7,5,1"
);
assert.strictEqual(
commands.companionLeaveIn30,
"set radio2.cross on\n" +
@@ -101,6 +109,10 @@ const generated = tool.configFromGenerator({
bw: "500",
sf: "8",
cr: "7",
normalfreq: "910.525",
normalbw: "62.5",
normalsf: "7",
normalcr: "5",
tx: "22",
});
assert.strictEqual(generated.startEpoch, config.startEpoch);
@@ -136,6 +148,18 @@ assert.throws(
() => tool.configFromSearch("?tx=61"),
/tx must be between/
);
assert.throws(
() => tool.configFromSearch("?normalbw=100"),
/normalbw must be one of/
);
const alternateReturn = tool.configFromSearch(
"?normalfreq=915.5&normalbw=125&normalsf=9&normalcr=6"
);
assert.strictEqual(
tool.commandsFor(alternateReturn, alternateReturn.startMs).stockCancelDuring,
"tempradio 915.5,125,9,6,1"
);
const changed = tool.configFromSearch(
"?start=1790035200&end=1790208000&freq=915.25&bw=125&sf=10&cr=5"
@@ -154,6 +178,10 @@ assert.strictEqual(shared.searchParams.get("end"), "2026-09-24T00:00:00.000Z");
assert.strictEqual(shared.searchParams.get("freq"), "915.25");
assert.strictEqual(shared.searchParams.get("tz"), "America/Los_Angeles");
assert.strictEqual(shared.searchParams.get("tx"), "22");
assert.strictEqual(shared.searchParams.get("normalfreq"), "910.525");
assert.strictEqual(shared.searchParams.get("normalbw"), "62.5");
assert.strictEqual(shared.searchParams.get("normalsf"), "7");
assert.strictEqual(shared.searchParams.get("normalcr"), "5");
assert.strictEqual(shared.searchParams.has("stale"), false);
assert.strictEqual(shared.hash, "#commands");