Skip to content

Commit 5f337cc

Browse files
authored
Improved roDeviceInfo.getConnectionInfo() by getting actual network information (#181)
* Added real `gateway` data on `connectionInfo` * Improved gateway retrieval * Improved gateway detection in Windows * Improved handling of async gateway retrieval * Prevent hanging promise * Try to get SSID * Updated util * Fixed getSSID()
1 parent 6b2ef83 commit 5f337cc

7 files changed

Lines changed: 192 additions & 40 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
"minimist": "^1.2.5",
8585
"mousetrap": "^1.6.5",
8686
"nanoid": "^5.0.9",
87+
"network": "^0.7.0",
8788
"node-ssdp": "^4.0.1",
8889
"postman-request": "^2.88.1-postman.33",
8990
"restana": "^4.9.9",

src/helpers/settings.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ export function setDeviceInfo(section, key, notifyApp) {
691691
global.sharedObject.deviceInfo[key] = newValue;
692692
if (notifyApp) {
693693
const window = BrowserWindow.fromId(1);
694-
window.webContents.send("setDeviceInfo", key, newValue);
694+
window?.webContents.send("setDeviceInfo", key, newValue);
695695
}
696696
}
697697
}

src/helpers/util.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
*
66
* Licensed under the MIT License. See LICENSE in the repository root for license information.
77
*--------------------------------------------------------------------------------------------*/
8+
import os from "os";
9+
import network from "network";
10+
import { execSync } from "child_process";
11+
12+
const isWindows = process.platform === "win32";
813

914
export function isValidIP(ip) {
1015
if (typeof ip !== "string") {
@@ -28,3 +33,105 @@ export function isValidUrl(string) {
2833
return false;
2934
}
3035
}
36+
37+
export function getLocalIps() {
38+
const ifaces = os.networkInterfaces();
39+
const ips = [];
40+
Object.keys(ifaces).forEach(function (ifname) {
41+
let alias = 0;
42+
ifaces[ifname].forEach(function (iface) {
43+
if ("IPv4" !== iface.family || iface.internal !== false) {
44+
// skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses
45+
return;
46+
}
47+
if (alias >= 1) {
48+
// this single interface has multiple ipv4 addresses
49+
console.log(`${ifname}:${alias}`, iface.address);
50+
ips.push(`${ifname}:${alias},${iface.address}`);
51+
} else {
52+
// this interface has only one ipv4 address
53+
console.log(ifname, iface.address);
54+
ips.push(`${ifname},${iface.address}`);
55+
}
56+
++alias;
57+
});
58+
});
59+
if (ips.length === 0) {
60+
ips.push("eth1,127.0.0.1");
61+
}
62+
return ips;
63+
}
64+
65+
export async function getGateway() {
66+
const gateWayData = { ip: "", name: "", type: "", ssid: "" };
67+
try {
68+
const gw = await getActiveInterface();
69+
gateWayData.ip = gw.gateway_ip ?? "";
70+
gateWayData.name = gw.name ?? "";
71+
gateWayData.type = gw.type === "Wireless" ? "WiFiConnection" : "WiredConnection";
72+
if (gateWayData.type === "WiFiConnection") {
73+
gateWayData.ssid = getSSID() ?? "WiFi";
74+
}
75+
console.log(
76+
`Gateway: ${gateWayData.ip} - Interface: ${gateWayData.name} - Type: ${gateWayData.type} - SSID: ${gateWayData.ssid}`
77+
);
78+
} catch (err) {
79+
console.error(`Unable to get the Network Gateway: ${err.message}`);
80+
}
81+
return gateWayData;
82+
}
83+
84+
async function getActiveInterface() {
85+
return await new Promise((resolve, reject) => {
86+
if (!isWindows) {
87+
network.get_active_interface((err, obj) => {
88+
if (err) {
89+
reject(err);
90+
} else {
91+
resolve(obj);
92+
}
93+
});
94+
} else {
95+
network.get_interfaces_list((err, list) => {
96+
if (err) {
97+
reject(err);
98+
} else {
99+
for (let iface of list) {
100+
if (iface.gateway_ip) {
101+
resolve(iface);
102+
break;
103+
}
104+
}
105+
}
106+
reject(new Error("No active interface found"));
107+
});
108+
}
109+
});
110+
}
111+
112+
function getSSID() {
113+
const platform = os.platform();
114+
let command;
115+
116+
if (platform === "win32") {
117+
command = "netsh wlan show interfaces";
118+
} else if (platform === "darwin") {
119+
command =
120+
"/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I";
121+
} else if (platform === "linux") {
122+
command = "iwgetid -r";
123+
}
124+
125+
let ssid;
126+
const result = execSync(command).toString();
127+
if (platform === "win32") {
128+
const match = result.match(/SSID\s*:\s*(.+)/);
129+
ssid = match ? match[1] : null;
130+
} else if (platform === "darwin") {
131+
const match = result.match(/ SSID: (.+)/);
132+
ssid = match ? match[1] : null;
133+
} else if (platform === "linux") {
134+
ssid = result.trim();
135+
}
136+
return ssid;
137+
}

src/helpers/window.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*---------------------------------------------------------------------------------------------
22
* BrightScript Simulation Desktop Application (https://github.com/lvcabral/brs-desktop)
33
*
4-
* Copyright (c) 2019-2024 Marcelo Lv Cabral. All Rights Reserved.
4+
* Copyright (c) 2019-2025 Marcelo Lv Cabral. All Rights Reserved.
55
*
66
* Licensed under the MIT License. See LICENSE in the repository root for license information.
77
*--------------------------------------------------------------------------------------------*/
@@ -201,7 +201,7 @@ export function closeChannel() {
201201
}
202202
}
203203

204-
export function reloadApp() {
204+
export function reloadDevice() {
205205
const window = BrowserWindow.fromId(1);
206206
if (window) {
207207
window.webContents.reloadIgnoringCache();

src/main.js

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
*--------------------------------------------------------------------------------------------*/
88
import path from "path";
99
import url from "url";
10-
import os from "os";
10+
import dns from "dns";
1111
import minimist from "minimist";
1212
import jetpack from "fs-jetpack";
13-
import { app, screen } from "electron";
13+
import { app, screen, BrowserWindow } from "electron";
1414
import { DateTime } from "luxon";
1515
import { setPassword, setPort, enableInstaller } from "./server/installer";
1616
import { initECP, enableECP } from "./server/ecp";
@@ -43,13 +43,17 @@ import {
4343
setAspectRatio,
4444
saveWindowState,
4545
} from "./helpers/window";
46+
import { getGateway, getLocalIps } from "./helpers/util";
4647
import { setupTitlebar, attachTitlebarToWindow } from "custom-electron-titlebar/main";
4748
import { randomUUID } from "crypto";
4849

4950
const isMacOS = process.platform === "darwin";
5051

52+
require("@electron/remote/main").initialize();
53+
5154
// Device Information Object
5255
const dt = DateTime.now().setZone("system");
56+
const localIps = getLocalIps();
5357
const deviceInfo = {
5458
developerId: "brs-dev-id", // Unique id to segregate registry data
5559
friendlyName: app.getName(),
@@ -64,15 +68,31 @@ const deviceInfo = {
6468
locale: "en_US",
6569
clockFormat: "12h",
6670
displayMode: "720p", // Options are: 480p (SD), 720p (HD), 1080p (FHD)
67-
connectionType: "WiFiConnection", // Options: "WiFiConnection", "WiredConnection", ""
68-
localIps: getLocalIps(),
71+
connectionInfo: {
72+
type: "WiredConnection",
73+
name: localIps[0].split(",")[0],
74+
gateway: "127.0.0.1",
75+
dns: dns.getServers(),
76+
quality: "Excellent",
77+
},
78+
localIps: localIps,
6979
startTime: Date.now(),
7080
maxSimulStreams: 2,
7181
audioVolume: 40,
7282
appList: [],
7383
};
7484

75-
require("@electron/remote/main").initialize();
85+
// Get Network Gateway
86+
getGateway().then((gateway) => {
87+
if (gateway.ip !== "") {
88+
deviceInfo.connectionInfo.gateway = gateway.ip;
89+
deviceInfo.connectionInfo.name = gateway.name;
90+
deviceInfo.connectionInfo.type = gateway.type;
91+
deviceInfo.connectionInfo.ssid = gateway.ssid;
92+
const window = BrowserWindow.fromId(1);
93+
window?.webContents.send("setDeviceInfo", "connectionInfo", deviceInfo.connectionInfo);
94+
}
95+
});
7696

7797
// Parse CLI parameters
7898
const argv = minimist(process.argv.slice(1), {
@@ -340,29 +360,3 @@ function setupEvents(mainWindow) {
340360
});
341361
});
342362
}
343-
344-
// Helper Functions
345-
function getLocalIps() {
346-
const ifaces = os.networkInterfaces();
347-
const ips = [];
348-
Object.keys(ifaces).forEach(function (ifname) {
349-
let alias = 0;
350-
ifaces[ifname].forEach(function (iface) {
351-
if ("IPv4" !== iface.family || iface.internal !== false) {
352-
// skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses
353-
return;
354-
}
355-
if (alias >= 1) {
356-
// this single interface has multiple ipv4 addresses
357-
console.log(`${ifname}:${alias}`, iface.address);
358-
ips.push(`${ifname}:${alias},${iface.address}`);
359-
} else {
360-
// this interface has only one ipv4 address
361-
console.log(ifname, iface.address);
362-
ips.push(`${ifname},${iface.address}`);
363-
}
364-
++alias;
365-
});
366-
});
367-
return ips;
368-
}

src/menu/deviceMenuTemplate.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
/*---------------------------------------------------------------------------------------------
22
* BrightScript Simulation Desktop Application (https://github.com/lvcabral/brs-desktop)
33
*
4-
* Copyright (c) 2019-2023 Marcelo Lv Cabral. All Rights Reserved.
4+
* Copyright (c) 2019-2025 Marcelo Lv Cabral. All Rights Reserved.
55
*
66
* Licensed under the MIT License. See LICENSE in the repository root for license information.
77
*--------------------------------------------------------------------------------------------*/
88
import { isECPEnabled, enableECP, disableECP } from "../server/ecp";
99
import { isTelnetEnabled, enableTelnet, disableTelnet } from "../server/telnet";
1010
import { isInstallerEnabled, enableInstaller, disableInstaller } from "../server/installer";
1111
import { setLocaleId, setDisplayOption, setPeerRoku } from "../helpers/settings";
12-
import { reloadApp } from "../helpers/window";
12+
import { reloadDevice } from "../helpers/window";
1313

1414
export const deviceMenuTemplate = {
1515
id: "device-menu",
@@ -190,7 +190,7 @@ export const deviceMenuTemplate = {
190190
label: "Reset Device",
191191
accelerator: "CmdOrCtrl+Shift+R",
192192
click: (item, window) => {
193-
reloadApp();
193+
reloadDevice();
194194
},
195195
},
196196
],

yarn.lock

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,14 +1626,19 @@ async-exit-hook@^2.0.1:
16261626
resolved "https://registry.yarnpkg.com/async-exit-hook/-/async-exit-hook-2.0.1.tgz#8bd8b024b0ec9b1c01cccb9af9db29bd717dfaf3"
16271627
integrity sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==
16281628

1629+
async@^1.5.2:
1630+
version "1.5.2"
1631+
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
1632+
integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==
1633+
16291634
async@^2.6.0:
16301635
version "2.6.4"
16311636
resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221"
16321637
integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==
16331638
dependencies:
16341639
lodash "^4.17.14"
16351640

1636-
async@^3.2.3:
1641+
async@^3.2.0, async@^3.2.3:
16371642
version "3.2.6"
16381643
resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce"
16391644
integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==
@@ -2225,6 +2230,13 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
22252230
dependencies:
22262231
delayed-stream "~1.0.0"
22272232

2233+
commander@2.9.0:
2234+
version "2.9.0"
2235+
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
2236+
integrity sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==
2237+
dependencies:
2238+
graceful-readlink ">= 1.0.0"
2239+
22282240
commander@^10.0.1:
22292241
version "10.0.1"
22302242
resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
@@ -3456,6 +3468,11 @@ graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0,
34563468
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
34573469
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
34583470

3471+
"graceful-readlink@>= 1.0.0":
3472+
version "1.0.1"
3473+
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
3474+
integrity sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==
3475+
34593476
har-schema@^2.0.0:
34603477
version "2.0.0"
34613478
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
@@ -3693,7 +3710,14 @@ iconv-corefoundation@^1.1.7:
36933710
cli-truncate "^2.1.0"
36943711
node-addon-api "^1.6.3"
36953712

3696-
iconv-lite@^0.6.2:
3713+
iconv-lite@^0.5.0:
3714+
version "0.5.2"
3715+
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.5.2.tgz#af6d628dccfb463b7364d97f715e4b74b8c8c2b8"
3716+
integrity sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==
3717+
dependencies:
3718+
safer-buffer ">= 2.1.2 < 3"
3719+
3720+
iconv-lite@^0.6.2, iconv-lite@^0.6.3:
36973721
version "0.6.3"
36983722
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
36993723
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
@@ -4490,11 +4514,29 @@ nanomatch@^1.2.13:
44904514
snapdragon "^0.8.1"
44914515
to-regex "^3.0.1"
44924516

4517+
needle@^3.0.0:
4518+
version "3.3.1"
4519+
resolved "https://registry.yarnpkg.com/needle/-/needle-3.3.1.tgz#63f75aec580c2e77e209f3f324e2cdf3d29bd049"
4520+
integrity sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==
4521+
dependencies:
4522+
iconv-lite "^0.6.3"
4523+
sax "^1.2.4"
4524+
44934525
neo-async@^2.6.2:
44944526
version "2.6.2"
44954527
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
44964528
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
44974529

4530+
network@^0.7.0:
4531+
version "0.7.0"
4532+
resolved "https://registry.yarnpkg.com/network/-/network-0.7.0.tgz#beb801e34448a4cec5f5b5857d20f1593328fb8e"
4533+
integrity sha512-AquYHEZFrPi1WPaMg+21iTKN7aMERP70frgK41lbTt/9tTQcwgaOtlqHRmVbxJjWYWJy033jUbA8xXhFArXodw==
4534+
dependencies:
4535+
async "^1.5.2"
4536+
commander "2.9.0"
4537+
needle "^3.0.0"
4538+
wmic "^1.0.1"
4539+
44984540
no-case@^3.0.4:
44994541
version "3.0.4"
45004542
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
@@ -5347,7 +5389,7 @@ safe-regex@^1.1.0:
53475389
dependencies:
53485390
ret "~0.1.10"
53495391

5350-
"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
5392+
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
53515393
version "2.1.2"
53525394
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
53535395
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
@@ -6277,6 +6319,14 @@ wildcard@^2.0.0:
62776319
resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67"
62786320
integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==
62796321

6322+
wmic@^1.0.1:
6323+
version "1.1.1"
6324+
resolved "https://registry.yarnpkg.com/wmic/-/wmic-1.1.1.tgz#e77f8ddea85f23fa77514e3d8e9de9c302447bf3"
6325+
integrity sha512-6lbonssALks49dX9bJTE8i54OTjbbLfd3IraFfG1ZR1ZrEbEynCt471IX5SfslZaFwISJKdUFHjOWHk0Brs5eg==
6326+
dependencies:
6327+
async "^3.2.0"
6328+
iconv-lite "^0.5.0"
6329+
62806330
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
62816331
version "7.0.0"
62826332
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"

0 commit comments

Comments
 (0)