diff --git a/static/index.html b/static/index.html
index d21c728..bd202c1 100644
--- a/static/index.html
+++ b/static/index.html
@@ -38,21 +38,22 @@
diff --git a/static/morse.mjs b/static/morse.mjs
index 54d134e..e14f4f6 100644
--- a/static/morse.mjs
+++ b/static/morse.mjs
@@ -189,6 +189,13 @@ class Keyer {
this.pauseMultiplier = multiplier
}
+ /**
+ * Delete anything left on the queue.
+ */
+ Flush() {
+ this.queue.splice(0)
+ }
+
/**
* Add to the output queue, and start processing the queue if it's not currently being processed.
*
diff --git a/static/repeaters.mjs b/static/repeaters.mjs
index df93647..541ef68 100644
--- a/static/repeaters.mjs
+++ b/static/repeaters.mjs
@@ -5,9 +5,9 @@ const Second = 1000 * Millisecond
const Minute = 60 * Second
export class Vail {
- constructor(name, rx) {
- this.name = name
+ constructor(rx, name) {
this.rx = rx
+ this.name = name
this.lagDurations = []
this.sent = []
@@ -110,10 +110,33 @@ export class Vail {
}
export class Null {
- constructor() {
+ constructor(rx) {
+ this.rx = rx
+ this.interval = setInterval(() => this.pulse(), 1 * Second)
}
- Transmit(time, duration, squelch=True) {
+ pulse() {
+ console.log("pulse")
+ this.rx(0, 0, {note: "local"})
+ }
+
+ Transmit(time, duration, squelch=true) {
+ }
+
+ Close() {
+ clearInterval(this.interval)
+ }
+}
+
+export class Echo {
+ constructor(rx, delay=0) {
+ this.rx = rx
+ this.delay = delay
+ this.Transmit(0, 0)
+ }
+
+ Transmit(time, duration, squelch=true) {
+ this.rx(time + this.delay, duration, {note: "local"})
}
Close() {
@@ -135,15 +158,13 @@ export class Fortune {
}
pulse() {
+ this.rx(0, 0, {note: "local"})
if (this.keyer.Busy()) {
return
}
let fortune = GetFortune()
this.keyer.EnqueueAsciiString(`${fortune}\x04 `)
- this.rx(0, 0, {
- note: "local",
- })
}
Transmit(time, duration, squelch=true) {
@@ -151,6 +172,7 @@ export class Fortune {
}
Close() {
+ this.keyer.Flush()
clearInterval(this.interval)
}
}
\ No newline at end of file
diff --git a/static/vail.mjs b/static/vail.mjs
index adbdf7a..9c45037 100644
--- a/static/vail.mjs
+++ b/static/vail.mjs
@@ -3,6 +3,9 @@ import * as Inputs from "./inputs.mjs"
import * as Repeaters from "./repeaters.mjs"
const DefaultRepeater = "General Chaos"
+const Millisecond = 1
+const Second = 1000 * Millisecond
+const Minute = 60 * Second
/**
* Pop up a message, using an MDL snackbar.
@@ -65,16 +68,27 @@ class VailClient {
this.rxDelay = Number(e.target.value)
})
+
// Fill in the name of our repeater
let repeaterElement = document.querySelector("#repeater").addEventListener("change", e => this.setRepeater(e.target.value.trim()))
- this.setRepeater(decodeURI(decodeURIComponent(window.location.hash.split("#")[1] || "")))
+ window.addEventListener("hashchange", () => this.hashchange())
+ this.hashchange()
+ }
+
+ /**
+ * Called when the hash part of the URL has changed.
+ */
+ hashchange() {
+ let hashParts = window.location.hash.split("#")
+
+ this.setRepeater(decodeURIComponent(hashParts[1] || ""))
}
/**
* Connect to a repeater by name.
*
- * In the future this may do some fancy switching logic to provide multiple types of repeaters.
- * For instance, I'd like to create a set of repeaters that run locally, for practice.
+ * This does some switching logic to provide multiple types of repeaters,
+ * like the Fortunes repeaters.
*
* @param {string} name Repeater name
*/
@@ -94,12 +108,11 @@ class VailClient {
}
// Set window URL
- let hash = name
- if (name == DefaultRepeater) {
- hash = ""
- }
- if (hash != window.location.hash) {
- window.location.hash = hash
+ let prevHash = window.location.hash
+ window.location.hash = (name == DefaultRepeater) ? "" : name
+ if (window.location.hash != prevHash) {
+ // We're going to get a hashchange event, which will re-run this method
+ return
}
if (this.repeater) {
@@ -107,17 +120,25 @@ class VailClient {
}
let rx = (w,d,s) => this.receive(w,d,s)
- // You can set the repeater name to "Fortunes: Pauses×10" for a nice and easy intro
+ // If there's a number in the name, store that for potential later use
+ let numberMatch = name.match(/[0-9]+/)
+ let number = 0
+ if (numberMatch) {
+ number = Number(numberMatch[0])
+ }
+
if (name.startsWith("Fortunes")) {
- let m = name.match(/[x×]([0-9]+)/)
- let mult = 1
- if (m) {
- mult = Number(m[1])
- }
- this.roboKeyer.SetPauseMultiplier(mult)
+ this.roboKeyer.SetPauseMultiplier(number || 1)
this.repeater = new Repeaters.Fortune(rx, this.roboKeyer)
+ } else if (name.startsWith("Echo")) {
+ let delayElement = document.querySelector("#rx-delay")
+ delayElement.value = (number || 2) * Second
+ delayElement.dispatchEvent(new Event("input"))
+ this.repeater = new Repeaters.Echo(rx)
+ } else if (name == "Null") {
+ this.repeater = new Repeaters.Null(rx)
} else {
- this.repeater = new Repeaters.Vail(name, rx)
+ this.repeater = new Repeaters.Vail(rx, name)
}
toast(`Now using repeater: ${name}`)
@@ -195,7 +216,6 @@ class VailClient {
this.clockOffset = stats.clockOffset || "?"
let now = Date.now()
when += this.rxDelay
- console.log(stats)
if (duration > 0) {
if (when < now) {