Zwei Widersprüche, die beim Durchsehen der offenen Punkte auffielen. Beide entstanden erst dadurch, dass der Kanalgraph seit dem letzten Commit die Wahrheit zeigt — Empfehlung und Kennzeichnung waren noch auf dem alten Stand. 1. Kanalempfehlung ignorierte die Kanalbreite. interferenceWeight() rechnete nur mit dem Abstand der Kanalnummern. Ein 40-MHz-Netz auf Kanal 1 belegt real 2402-2442 MHz und damit auch Kanal 6 (2437), wurde wegen |1-6| = 5 aber als "stört nicht" gewertet. Gerechnet wird jetzt in MHz, mit derselben occupiedRange(), die auch das Diagramm zeichnet. Belegt mit tools/test-recommend.mjs: in zwei von drei realistischen Lagen nennt die alte Formel einen ANDEREN Kanal als den tatsächlich besten — z.B. bei einem starken 40-MHz-Netz auf Kanal 1 empfahl sie Kanal 6, obwohl dieses Netz genau dorthin reicht (richtig ist Kanal 11). In der Demo-Lage ändert sich die Spitzenempfehlung nicht, nur die Bewertung der übrigen Kanäle (K6 von 0,62 auf 0,80). 2. DFS-Kanäle 52-64 waren im Diagramm nicht als solche erkennbar. Der Block hieß "UNII-1/2A" und trug keine DFS-Kennzeichnung, während channelWarnings() Kanal 52-144 als DFS behandelt. Ein im Diagramm "frei" wirkender Kanal 56 hätte den Kunden ungewollt auf DFS gesetzt (möglicher Radar-Zwangswechsel), obwohl die Warnung darunter das Gegenteil sagte. UNII-1 (36-48) und UNII-2A (52-64) sind jetzt getrennte Blöcke mit korrekter Kennzeichnung. Damit die zusätzliche Aufteilung nicht zu mehr Scrollen führt: ein Block ohne Netze wird kompakt gezeichnet (ohne dBm-Skala, ~1/4 der Höhe) statt in voller Größe. Er bleibt sichtbar — er ist die Antwort auf "wo ist noch Platz". Nebenbei im Render-Werkzeug behoben: es stapelte alle Segmente mit gleicher Höhe und erzeugte dadurch künstliche Lücken im Testbild, die es in der App nicht gibt.
61 lines
2.6 KiB
JavaScript
61 lines
2.6 KiB
JavaScript
import { transformSync } from 'esbuild';
|
|
import { readFileSync, writeFileSync } from 'fs';
|
|
import { pathToFileURL } from 'url';
|
|
|
|
function build(src, out) {
|
|
let js = transformSync(readFileSync(src, 'utf8'), { loader: 'ts', format: 'esm', target: 'node20' }).code;
|
|
js = js.replace(/from\s+['"]\.\/chart['"]/g, "from './chart.js'");
|
|
writeFileSync(out, js);
|
|
}
|
|
build('src/lib/wifi/chart.ts', '/tmp/chart.js');
|
|
build('src/lib/wifi/recommend.ts', '/tmp/recommend.js');
|
|
const { recommend24GhzChannels } = await import(pathToFileURL('/tmp/recommend.js').href);
|
|
|
|
function alt(nets) {
|
|
const w = (c, n) => {
|
|
const d = Math.abs(c - n.channel);
|
|
if (d >= 5) return 0;
|
|
return (1 - d / 5) * Math.min(1, Math.max(0.1, (n.rssi + 90) / 60));
|
|
};
|
|
return [1, 6, 11].map((channel) => ({
|
|
channel, load: Math.round(nets.reduce((s, n) => s + w(channel, n), 0) * 100) / 100,
|
|
})).sort((a, b) => a.load - b.load);
|
|
}
|
|
|
|
const FAELLE = [
|
|
{
|
|
name: 'Demo-Lage (wie im Screenshot)',
|
|
nets: [
|
|
{ channel: 6, frequency: 2437, rssi: -53, band: '2.4 GHz', widthMhz: 20 },
|
|
{ channel: 11, frequency: 2462, rssi: -61, band: '2.4 GHz', widthMhz: 20 },
|
|
{ channel: 1, frequency: 2412, rssi: -75, band: '2.4 GHz', widthMhz: 40, centerFreq0: 2422 },
|
|
{ channel: 11, frequency: 2462, rssi: -77, band: '2.4 GHz', widthMhz: 20 },
|
|
{ channel: 13, frequency: 2472, rssi: -85, band: '2.4 GHz', widthMhz: 20 },
|
|
],
|
|
},
|
|
{
|
|
name: 'STARKES 40-MHz-Netz auf Kanal 1, schwache Nachbarn auf 6 und 11',
|
|
nets: [
|
|
{ channel: 1, frequency: 2412, rssi: -45, band: '2.4 GHz', widthMhz: 40, centerFreq0: 2422 },
|
|
{ channel: 6, frequency: 2437, rssi: -85, band: '2.4 GHz', widthMhz: 20 },
|
|
{ channel: 11, frequency: 2462, rssi: -80, band: '2.4 GHz', widthMhz: 20 },
|
|
],
|
|
},
|
|
{
|
|
name: 'Starkes 40-MHz-Netz auf Kanal 9 (überdeckt 6 UND 11)',
|
|
nets: [
|
|
{ channel: 9, frequency: 2452, rssi: -50, band: '2.4 GHz', widthMhz: 40, centerFreq0: 2442 },
|
|
{ channel: 1, frequency: 2412, rssi: -70, band: '2.4 GHz', widthMhz: 20 },
|
|
],
|
|
},
|
|
];
|
|
|
|
for (const f of FAELLE) {
|
|
const neu = recommend24GhzChannels(f.nets);
|
|
const a = alt(f.nets);
|
|
const kippt = neu[0].channel !== a[0].channel;
|
|
console.log(`\n${f.name}`);
|
|
console.log(` ALT: ${a.map(r => `K${r.channel}=${r.load}`).join(' ')} -> empfiehlt Kanal ${a[0].channel}`);
|
|
console.log(` NEU: ${neu.map(r => `K${r.channel}=${r.load}`).join(' ')} -> empfiehlt Kanal ${neu[0].channel}`);
|
|
console.log(` ${kippt ? '>>> EMPFEHLUNG KIPPT — alte Formel hätte den falschen Kanal genannt' : ' (gleiche Empfehlung, nur andere Bewertung)'}`);
|
|
}
|