Add gateway auto-detection and rename to Local CPE
Local CPE (192.168.100.1) is always monitored. On startup, probe 192.168.1.1, 192.168.0.1, 192.168.8.1, and 10.0.0.1 in parallel and add whichever responds first as "Local Gateway".
This commit is contained in:
parent
83bd23945c
commit
b23da0797e
10
README.md
10
README.md
@ -53,8 +53,14 @@ code lives in `src/main.js` with a class-based architecture:
|
|||||||
|
|
||||||
- **11 WAN hosts**: datavi.be, Anthropic API, OpenAI API, AWS, GCP, Azure,
|
- **11 WAN hosts**: datavi.be, Anthropic API, OpenAI API, AWS, GCP, Azure,
|
||||||
DigitalOcean, Cloudflare, Fastly, Akamai, GitHub
|
DigitalOcean, Cloudflare, Fastly, Akamai, GitHub
|
||||||
- **1 Local host**: Local Gateway (192.168.100.1), tracked separately from WAN
|
- **Local CPE**: Cable modem at 192.168.100.1 (always monitored)
|
||||||
stats
|
- **Local Gateway**: Auto-detected on startup by probing common default gateway
|
||||||
|
addresses (192.168.1.1, 192.168.0.1, 192.168.8.1, 10.0.0.1); first responder
|
||||||
|
wins. Note: modern browsers enforce Private Network Access restrictions that
|
||||||
|
block public-origin pages from reaching RFC1918 addresses, so local targets
|
||||||
|
only work when NetWatch is served from localhost or a private address.
|
||||||
|
|
||||||
|
Local hosts are tracked separately from WAN stats.
|
||||||
|
|
||||||
### Latency measurement
|
### Latency measurement
|
||||||
|
|
||||||
|
|||||||
69
src/main.js
69
src/main.js
@ -2,6 +2,9 @@ import "./styles.css";
|
|||||||
|
|
||||||
// --- Configuration -----------------------------------------------------------
|
// --- Configuration -----------------------------------------------------------
|
||||||
|
|
||||||
|
// Timing, axis labels, and display constants. Latency above maxLatency is
|
||||||
|
// clamped to "unreachable". The history buffer holds maxHistoryPoints
|
||||||
|
// samples (historyDuration / updateInterval).
|
||||||
const CONFIG = Object.freeze({
|
const CONFIG = Object.freeze({
|
||||||
updateInterval: 2000,
|
updateInterval: 2000,
|
||||||
historyDuration: 300,
|
historyDuration: 300,
|
||||||
@ -15,6 +18,9 @@ const CONFIG = Object.freeze({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// WAN endpoints to monitor. These are used for the aggregate health/stats
|
||||||
|
// display (min/max/avg). Ordered: personal, LLM APIs, big-3 cloud, then
|
||||||
|
// CDN/hosting/other.
|
||||||
const WAN_HOSTS = [
|
const WAN_HOSTS = [
|
||||||
{ name: "datavi.be", url: "https://datavi.be" },
|
{ name: "datavi.be", url: "https://datavi.be" },
|
||||||
{ name: "Anthropic API", url: "https://api.anthropic.com" },
|
{ name: "Anthropic API", url: "https://api.anthropic.com" },
|
||||||
@ -29,7 +35,55 @@ const WAN_HOSTS = [
|
|||||||
{ name: "GitHub", url: "https://github.com" },
|
{ name: "GitHub", url: "https://github.com" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const LOCAL_HOSTS = [{ name: "Local Gateway", url: "http://192.168.100.1" }];
|
// The cable modem / CPE upstream of the local gateway — always monitored.
|
||||||
|
const LOCAL_CPE = { name: "Local CPE", url: "http://192.168.100.1" };
|
||||||
|
|
||||||
|
// Common default gateway addresses. On startup we probe each one and use
|
||||||
|
// whichever responds first as the "Local Gateway" monitor target.
|
||||||
|
//
|
||||||
|
// NOTE: Modern browsers enforce Private Network Access (PNA) restrictions
|
||||||
|
// that block pages served from public origins from making requests to
|
||||||
|
// RFC1918 addresses. These local targets will likely only work when
|
||||||
|
// NetWatch is served from localhost or another private address.
|
||||||
|
const GATEWAY_CANDIDATES = [
|
||||||
|
"http://192.168.1.1",
|
||||||
|
"http://192.168.0.1",
|
||||||
|
"http://192.168.8.1",
|
||||||
|
"http://10.0.0.1",
|
||||||
|
];
|
||||||
|
|
||||||
|
// --- Gateway Detection -------------------------------------------------------
|
||||||
|
|
||||||
|
// Probe each gateway candidate with a short timeout. Returns the first one
|
||||||
|
// that responds, or null if none do. We race them all in parallel and take
|
||||||
|
// whichever wins.
|
||||||
|
async function detectGateway() {
|
||||||
|
try {
|
||||||
|
const result = await Promise.any(
|
||||||
|
GATEWAY_CANDIDATES.map(async (url) => {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeoutId = setTimeout(() => controller.abort(), 1500);
|
||||||
|
try {
|
||||||
|
await fetch(url, {
|
||||||
|
method: "HEAD",
|
||||||
|
mode: "no-cors",
|
||||||
|
cache: "no-store",
|
||||||
|
signal: controller.signal,
|
||||||
|
});
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
return { name: "Local Gateway", url };
|
||||||
|
} catch {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
throw new Error("no response");
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
} catch {
|
||||||
|
// All candidates failed
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- App State ---------------------------------------------------------------
|
// --- App State ---------------------------------------------------------------
|
||||||
|
|
||||||
@ -75,9 +129,9 @@ class HostState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AppState {
|
class AppState {
|
||||||
constructor() {
|
constructor(localHosts) {
|
||||||
this.wan = WAN_HOSTS.map((h) => new HostState(h));
|
this.wan = WAN_HOSTS.map((h) => new HostState(h));
|
||||||
this.local = LOCAL_HOSTS.map((h) => new HostState(h));
|
this.local = localHosts.map((h) => new HostState(h));
|
||||||
this.paused = false;
|
this.paused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,8 +597,13 @@ function handleResize(state) {
|
|||||||
|
|
||||||
// --- Bootstrap ---------------------------------------------------------------
|
// --- Bootstrap ---------------------------------------------------------------
|
||||||
|
|
||||||
function init() {
|
async function init() {
|
||||||
const state = new AppState();
|
// Probe common gateway IPs to find the local router
|
||||||
|
const gateway = await detectGateway();
|
||||||
|
const localHosts = [LOCAL_CPE];
|
||||||
|
if (gateway) localHosts.push(gateway);
|
||||||
|
|
||||||
|
const state = new AppState(localHosts);
|
||||||
buildUI(state);
|
buildUI(state);
|
||||||
|
|
||||||
document
|
document
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user