UNPKG

asusroutermonitor

Version:
406 lines (405 loc) 14.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RouterInfo = void 0; const node_fetch_1 = require("node-fetch"); var ClientType; (function (ClientType) { ClientType[ClientType["DEVICE"] = 0] = "DEVICE"; ClientType[ClientType["UNK_1"] = 1] = "UNK_1"; ClientType[ClientType["UNK_7"] = 7] = "UNK_7"; ClientType[ClientType["UNK_18"] = 18] = "UNK_18"; ClientType[ClientType["LINUX"] = 22] = "LINUX"; ClientType[ClientType["ROUTER"] = 24] = "ROUTER"; ClientType[ClientType["UNK_34"] = 34] = "UNK_34"; // Unsure, ASUS_Phone })(ClientType || (ClientType = {})); ; var IPMethod; (function (IPMethod) { IPMethod["STATIC"] = "Manual"; IPMethod["DHCP"] = "Dhcp"; IPMethod["MANUAL"] = "Manual"; IPMethod["OFFLINE"] = "Offline"; })(IPMethod || (IPMethod = {})); ; var OPMode; (function (OPMode) { OPMode[OPMode["NONE"] = 0] = "NONE"; OPMode[OPMode["WIRELESS_ROUTER"] = 1] = "WIRELESS_ROUTER"; OPMode[OPMode["OP_RE_ITEM"] = 2] = "OP_RE_ITEM"; OPMode[OPMode["OP_AP_ITEM"] = 3] = "OP_AP_ITEM"; OPMode[OPMode["OP_MB_ITME"] = 4] = "OP_MB_ITME"; })(OPMode || (OPMode = {})); ; // TODO: This pains me greatly but I don't know what to do. I can't start with a number. var WirelessBand; (function (WirelessBand) { WirelessBand[WirelessBand["None"] = 0] = "None"; WirelessBand[WirelessBand["2_4GHZ"] = 1] = "2_4GHZ"; WirelessBand[WirelessBand["5GHZ"] = 2] = "5GHZ"; })(WirelessBand || (WirelessBand = {})); ; var InternetMode; (function (InternetMode) { InternetMode["ALLOW"] = "allow"; InternetMode["BLOCK"] = "block"; InternetMode["TIME"] = "time"; })(InternetMode || (InternetMode = {})); ; const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); class RouterInfo { /** * Create the object and connect with the router * @param {string} ip Router IP Address */ constructor(ip) { this.ip = ip; this.url = `http://${ip}/appGet.cgi`; this.headers = null; } /** * Authenticate with the router * @param {string} ip Router IP Address * @param {string} username Root username * @param {string} password Root password * @returns {boolean} Whether authentication was successful. */ async authenticate(username, password) { const loginToken = Buffer.from(`${username}:${password}`).toString('base64'); this.headers = { 'user-agent': 'asusrouter-Android-DUTUtil-1.0.0.245', 'content-type': 'application/x-www-form-urlencoded' }; const req = await (0, node_fetch_1.default)(`http://${this.ip}/login.cgi`, { method: 'POST', headers: this.headers, body: `login_authorization=${loginToken}` }); if (req.status !== 200) { return false; } const res = await req.json(); if (!res.asus_token) { return false; } this.headers.cookie = `asus_token=${res.asus_token}`; return true; } /** * Private get method to execute a hook on the router and return the result * @param {string} command Command to send to the router * @returns {string|null} String result from the router or null */ async get(command) { if (this.headers === null) { return null; } const req = await (0, node_fetch_1.default)(this.url, { method: 'POST', headers: this.headers, body: `hook=${command}` }); if (req.status !== 200) { return null; } return await req.text(); } /** * Gets uptime of the router * @returns {UptimeResponse|null} an object with since and uptime, or null. */ async getUptime() { const r = await this.get('uptime()'); if (r === null) { return null; } const since = r.split(':')[1].split('(')[0]; const uptime = r.split('(')[1].split(' ')[0]; return { since: new Date(since), uptime: Number(uptime) }; } /** * Get the uptime of the router in seconds * @returns {number} Uptime in seconds */ async getUptimeSecs() { const r = await this.get('uptime()'); if (r === null) { return null; } const uptime = r.split('(')[1].split(' ')[0]; return Number(uptime); } /** * Gets the memory usage of the router * @returns {MemoryUsage|null} Memory usage in bytes or null */ async getMemoryUsage() { const r = await this.get('memory_usage()'); if (r === null) { return null; } // TODO: This will throw an error if the json is invalid. const usage = JSON.parse(`{${r.slice(17)}`); return { mem_total: Number(usage.mem_total), mem_free: Number(usage.mem_free), mem_used: Number(usage.mem_used) }; } /** * Gets the CPU usage of the router * @returns {CPUUsage|null} CPU usage or null */ async getCPUUsage() { const r = await this.get('cpu_usage()'); if (r === null) { return null; } // TODO: This will throw an error if the json is invalid. const usage = JSON.parse(`{${r.slice(14)}`); return { cpu1_total: Number(usage.cpu1_total), cpu1_usage: Number(usage.cpu1_usage), cpu2_total: Number(usage.cpu2_total), cpu2_usage: Number(usage.cpu2_total) }; } /** * Gets a full list of client information as well as the connected mac addresses and client api level. * @returns {ClientFullInfo|null} List of client information or null */ async getClientsFullInfo() { const r = await this.get('get_clientlist()'); if (r === null) { return null; } const clients = JSON.parse(r); const clientFullInfo = { clientList: [], macList: clients.maclist, clientAPILevel: clients.ClientAPILevel }; for (const mac in clients.get_clientlist) { if (mac === 'macList' || mac === 'ClientAPILevel') { continue; } const oldClient = clients.get_clientlist[mac]; const client = { type: Number(oldClient.type), defaultType: Number(oldClient.defaultType), name: oldClient.name, nickName: oldClient.nickName, ip: oldClient.ip, mac: oldClient.mac, from: oldClient.from, macRepeat: !!Number(oldClient.macRepeat), isGateway: !!Number(oldClient.isGateway), isWebServer: !!Number(oldClient.isWebServer), isPrinter: !!Number(oldClient.isPrinter), isITunes: !!Number(oldClient.isITunes), dpiType: oldClient.dpiType, dpiDevice: oldClient.dpiDevice, vendor: oldClient.vendor, isWL: Number(oldClient.isWL), isGN: oldClient.isGN, isOnline: !!Number(oldClient.isOnline), ssid: oldClient.ssid, isLogin: !!Number(oldClient.isLogin), opMode: Number(oldClient.opMode), rssi: Number(oldClient.rssi), curTx: Number(oldClient.curTx), curRx: Number(oldClient.curRx), totalTx: Number(oldClient.totalTx), totalRx: Number(oldClient.totalRx), wlConnectTime: oldClient.wlConnectTime, ipMethod: oldClient.ipMethod, ROG: !!Number(oldClient.ROG), group: oldClient.group, callback: oldClient.callback, keeparp: oldClient.keeparp, qosLevel: oldClient.qosLevel, wtFast: oldClient.wtfast, internetMode: oldClient.internetMode, internetState: oldClient.internetState, amesh_isReClient: !!Number(oldClient.amesh_isReClient), amesh_papMac: oldClient.amesh_papMac, amesh_bind_mac: oldClient.amesh_bind_mac, amesh_bind_band: oldClient.amesh_bind_band }; clientFullInfo.clientList.push(client); } return clientFullInfo; } /** * Gets the total traffic since last restart in Megabits * @returns {Traffic|null} Sent and received Megabits since last boot or null */ async getTotalTraffic() { const r = await this.get('netdev(appobj)'); if (r === null) { return null; } const traffic = JSON.parse(r); const tx = parseInt(traffic.netdev.INTERNET_tx, 16) * 8 / 1024 / 1024 / 2; const rx = parseInt(traffic.netdev.INTERNET_rx, 16) * 8 / 1024 / 1024 / 2; return { sent: tx, recv: rx }; } /** * Averages the network traffic over 2 seconds in Megabits * @returns {Traffic|null} Current network traffic in Mbit/s */ async getTraffic() { const start = await this.get('netdev(appobj)'); await sleep(2000); const end = await this.get('netdev(appobj)'); if (start === null || end === null) { return null; } const startTraffic = JSON.parse(start); const endTraffic = JSON.parse(end); let tx = parseInt(endTraffic.netdev.INTERNET_tx, 16) * 8 / 1024 / 1024 / 2; tx -= parseInt(startTraffic.netdev.INTERNET_tx, 16) * 8 / 1024 / 1024 / 2; let rx = parseInt(endTraffic.netdev.INTERNET_rx, 16) * 8 / 1024 / 1024 / 2; rx -= parseInt(startTraffic.netdev.INTERNET_rx, 16) * 8 / 1024 / 1024 / 2; return { sent: tx, recv: rx }; } /** * Gets the status of the current WAN link * @returns {WanStatus|null} Status information about the currnet WAN link or null */ async getWanStatus() { const r = await this.get('wanlink()'); if (r === null) { return null; } const status = {}; for (const line of r.split('\n')) { if (!line.includes('return ') || !line.includes('wanlink_')) { continue; } const key = line.split('(')[0].split('_')[1]; const value = line.split(' ')[4].split(';')[0].replaceAll('\'', ''); status[key] = Number(value) ? Number(value) : value; } return status; } /** * Checks if the WAN link is connected * @returns {boolean|null} Whether the WAN link is connected or null */ async isWanOnline() { const r = await this.get('wanlink()'); if (r === null) { return null; } return r.includes('wanlink_status() { return 1;}'); } // TODO: Add a custom type for this, I haven't yet because I'm lazy and it's large /** * Gets the routers current settings * @returns {Settings} The router settings */ async getSettings() { const rawSettings = ['time_zone', 'time_zone_dst', 'time_zone_x', 'time_zone_dstoff', 'time_zone', 'ntp_server0', 'acs_dfs', 'productid', 'apps_sq', 'lan_hwaddr', 'lan_ipaddr', 'lan_proto', 'x_Setting', 'label_mac', 'lan_netmask', 'lan_gateway', 'http_enable', 'https_lanport', 'wl0_country_code', 'wl1_country_code']; const settings = {}; for (const setting of rawSettings) { const r = await this.get(`nvram_get(${setting})`); if (r === null) { continue; } settings[setting] = JSON.parse(r)[setting]; } return settings; } /** * Gets the IP address of the router * @returns The IP address of the router */ async getLanIPAddress() { const r = await this.get('nvram(lan_ipaddr)'); if (r === null) { return null; } return JSON.parse(r).lan_ipaddr; } /** * Gets the netmask of the router * @returns {string|null} Router netmask or null */ async getLanNetmask() { const r = await this.get('nvram(lan_netmask)'); if (r === null) { return null; } return JSON.parse(r).lan_netmask; } /** * Gets the ip address of the gateway for the LAN network * @returns {string|null} IP address of the gateway */ async getLanGateway() { const r = await this.get('nvram(lan_gateway)'); if (r === null) { return null; } return JSON.parse(r).lan_gateway; } /** * Gets a list of DHCP leases * @returns {DHCPEntry[]|null} List of DHCP entries or null */ async getDHCPList() { const r = await this.get('dhcpLeaseMacList()'); if (r === null) { return null; } const list = []; for (const entry of JSON.parse(r).dhcpLeaseMacList) { list.push({ mac: entry[0], name: decodeURIComponent(entry[1]) }); } return list; } /** * Gets info on all currently online clients * @returns {ClientInfo[]|null} Client info on all online clients or null */ async getOnlineClients() { const clients = await this.getClientsFullInfo(); if (clients === null) { return null; } const list = []; for (const client of clients.clientList) { if (!client.isOnline) { continue; } list.push(client); } return list; } /** * Gets info on a single client * @param clientMac MAC address of the requested client * @returns {ClientInfo|null} The client info or null */ async getClientInfo(clientMac) { const clients = await this.getClientsFullInfo(); if (clients === null) { return null; } return clients.clientList.filter((x => x.mac === clientMac))[0] || null; } } exports.RouterInfo = RouterInfo; ;