wifi-radar
Version:
Comprehensive WiFi network analysis & performance testing tool for macOS - speed tests, latency analysis, health diagnostics, QoS analysis & more
213 lines β’ 9.96 kB
JavaScript
import chalk from 'chalk';
export class TopologyMapper {
generateTopology(networks, devices) {
const currentNetwork = networks.find(n => n.isConnected);
const relationships = this.generateRelationships(networks, devices);
return {
router: {
mac: currentNetwork?.bssid || 'unknown',
ip: '192.168.1.1', // Default assumption
vendor: this.getRouterVendor(currentNetwork?.bssid),
model: 'Unknown Router'
},
devices,
networks,
relationships
};
}
renderTopologyASCII(topology) {
const lines = [];
// Header
lines.push(chalk.cyan.bold('π NETWORK TOPOLOGY MAP'));
lines.push(chalk.gray('β'.repeat(50)));
lines.push('');
// Router/Gateway
const router = topology.router;
lines.push(chalk.yellow.bold(`π‘ GATEWAY: ${router.vendor || 'Unknown'}`));
lines.push(chalk.gray(` MAC: ${router.mac}`));
lines.push(chalk.gray(` IP: ${router.ip}`));
lines.push('');
// Connected Network
const connectedNet = topology.networks.find(n => n.isConnected);
if (connectedNet) {
lines.push(chalk.green.bold(`π CONNECTED TO: ${connectedNet.ssid}`));
lines.push(chalk.gray(` Channel: ${connectedNet.channel} (${this.getFrequencyBand(connectedNet.frequency)})`));
lines.push(chalk.gray(` Signal: ${this.formatSignalStrength(connectedNet.signal)}`));
lines.push(chalk.gray(` Security: ${connectedNet.security.join(', ')}`));
lines.push('');
}
// Device Tree
lines.push(chalk.blue.bold('π± CONNECTED DEVICES'));
lines.push('');
if (topology.devices.length === 0) {
lines.push(chalk.gray(' No devices detected'));
}
else {
topology.devices.forEach((device, index) => {
const isLast = index === topology.devices.length - 1;
const prefix = isLast ? 'βββ ' : 'βββ ';
const deviceIcon = this.getDeviceIcon(device.deviceType);
lines.push(chalk.white(`${prefix}${deviceIcon} ${device.hostname || 'Unknown Device'}`));
lines.push(chalk.gray(`β MAC: ${device.mac}`));
lines.push(chalk.gray(`β IP: ${device.ip || 'Unknown'}`));
lines.push(chalk.gray(`β Type: ${device.deviceType || 'unknown'}`));
if (device.vendor) {
lines.push(chalk.gray(`β Vendor: ${device.vendor}`));
}
if (!isLast)
lines.push('β');
});
}
lines.push('');
// Nearby Networks
const nearbyNetworks = topology.networks.filter(n => !n.isConnected);
if (nearbyNetworks.length > 0) {
lines.push(chalk.magenta.bold('πΆ NEARBY NETWORKS'));
lines.push('');
nearbyNetworks
.sort((a, b) => b.signal - a.signal)
.slice(0, 10) // Top 10 networks
.forEach(network => {
const signalBars = this.getSignalBars(network.signal);
const securityIcon = network.security.includes('Open') ? 'π' : 'π';
lines.push(chalk.white(`${signalBars} ${securityIcon} ${network.ssid}`));
lines.push(chalk.gray(` Channel ${network.channel} β’ ${this.formatSignalStrength(network.signal)} β’ ${network.security.join(', ')}`));
});
}
return lines.join('\n');
}
renderInteractiveMap(topology) {
const lines = [];
// ASCII Art Network Diagram
lines.push(chalk.cyan.bold(' π INTERACTIVE NETWORK MAP'));
lines.push('');
lines.push(' βββββββββββββββ');
lines.push(' β INTERNET β');
lines.push(' ββββββββ¬βββββββ');
lines.push(' β');
lines.push(' ββββββββΌβββββββ');
lines.push(` β ${chalk.yellow('ROUTER')} β`);
lines.push(` β ${topology.router.vendor || 'Unknown'} β`);
lines.push(' ββββββββ¬βββββββ');
lines.push(' β');
lines.push(' ββββββββΌβββββββ');
lines.push(` β ${chalk.green('WiFi Network')} β`);
const connectedNet = topology.networks.find(n => n.isConnected);
if (connectedNet) {
lines.push(` β ${connectedNet.ssid.substring(0, 10)} β`);
}
else {
lines.push(' β Disconnected β');
}
lines.push(' βββββββ¬ββββββββ');
lines.push(' β');
// Device connections
if (topology.devices.length > 0) {
const deviceCount = Math.min(topology.devices.length, 3);
if (deviceCount === 1) {
lines.push(' β');
lines.push(' βββββββΌββββββ');
lines.push(` β ${this.getDeviceIcon(topology.devices[0].deviceType)} Device 1 β`);
lines.push(' βββββββββββββ');
}
else {
// Multiple devices in tree structure
lines.push(' βββββββΌββββββ');
for (let i = 0; i < deviceCount; i++) {
const device = topology.devices[i];
if (i === 0) {
lines.push(` βββββββββΌββββββ β βββββββΌββββββββ`);
lines.push(` β ${this.getDeviceIcon(device.deviceType)} Device ${i + 1} β β β ${this.getDeviceIcon(topology.devices[1]?.deviceType || 'unknown')} Device 2 β`);
lines.push(` βββββββββββββββ β βββββββββββββββ`);
if (deviceCount > 2) {
lines.push(' β');
lines.push(` βββββββββΌββββββ`);
lines.push(` β ${this.getDeviceIcon(topology.devices[2].deviceType)} Device 3 β`);
lines.push(' βββββββββββββββ');
}
break;
}
}
}
}
else {
lines.push(' β');
lines.push(' βββββββΌββββββ');
lines.push(' β No Devicesβ');
lines.push(' βββββββββββββ');
}
return lines.join('\n');
}
generateRelationships(networks, devices) {
const relationships = [];
// Connect all devices to the router
const connectedNetwork = networks.find(n => n.isConnected);
if (connectedNetwork) {
devices.forEach(device => {
relationships.push({
from: connectedNetwork.bssid,
to: device.mac,
type: 'connected',
strength: device.signal || 80 // Default strength
});
});
}
return relationships;
}
getRouterVendor(bssid) {
if (!bssid)
return undefined;
const oui = bssid.substring(0, 8).toUpperCase();
const vendors = {
'00:1B:63': 'Apple',
'00:25:00': 'Apple',
'3C:15:C2': 'Apple',
'44:D9:E7': 'TP-Link',
'98:DE:D0': 'Netgear',
'A0:63:91': 'Linksys'
};
return vendors[oui];
}
getDeviceIcon(deviceType) {
const icons = {
phone: 'π±',
laptop: 'π»',
tablet: 'π±',
iot: 'π ',
unknown: 'β'
};
return icons[deviceType] || icons.unknown;
}
getSignalBars(signal) {
if (signal >= -30)
return chalk.green('β°β°β°β°β°');
if (signal >= -50)
return chalk.green('β°β°β°β°β±');
if (signal >= -60)
return chalk.yellow('β°β°β°β±β±');
if (signal >= -70)
return chalk.yellow('β°β°β±β±β±');
if (signal >= -80)
return chalk.red('β°β±β±β±β±');
return chalk.red('β±β±β±β±β±');
}
formatSignalStrength(signal) {
const strength = signal >= -50 ? 'Excellent' :
signal >= -60 ? 'Good' :
signal >= -70 ? 'Fair' : 'Poor';
const color = signal >= -50 ? chalk.green :
signal >= -60 ? chalk.yellow :
signal >= -70 ? chalk.yellow : chalk.red;
return color(`${signal} dBm (${strength})`);
}
getFrequencyBand(frequency) {
if (frequency >= 2400 && frequency <= 2500)
return '2.4 GHz';
if (frequency >= 5000 && frequency <= 6000)
return '5 GHz';
if (frequency >= 6000 && frequency <= 7000)
return '6 GHz';
return 'Unknown';
}
}
//# sourceMappingURL=topology.js.map