feat: connect 消息上报 local_ip 和 external_ip
Made-with: Cursor
This commit is contained in:
@@ -8,7 +8,7 @@ const { getBoxId } = require('./fingerprint');
|
||||
const { collect } = require('./metrics');
|
||||
const { getDashboardInfo, startTtyd, FrpcManager } = require('./frpc'); // getDashboardInfo 也用于心跳中定期刷新
|
||||
const { ProvisionManager } = require('./provisioning');
|
||||
const { hasInternet } = require('./network');
|
||||
const { hasInternet, getLocalIps } = require('./network');
|
||||
const led = require('./led');
|
||||
|
||||
const MAX_BACKOFF_MS = 60_000;
|
||||
@@ -35,6 +35,7 @@ class ClawClient {
|
||||
this._frpc = new FrpcManager();
|
||||
this._dashInfo = {};
|
||||
this._hbCount = 0; // 心跳计数器,用于定期刷新 dashboard 信息
|
||||
this._externalIp = null; // 外网 IP(连接时查询一次,用于服务端地理位置解析)
|
||||
|
||||
// WS 层活性检测
|
||||
this._pingTimer = null;
|
||||
@@ -111,6 +112,27 @@ class ClawClient {
|
||||
startTtyd().catch(e => log.warn('ttyd', '启动失败:', e.message)),
|
||||
]);
|
||||
this._dashInfo = dashInfo || {};
|
||||
|
||||
// 查询外网 IP(用于服务端地理位置解析),失败不阻断连接
|
||||
try {
|
||||
const https = require('https');
|
||||
this._externalIp = await new Promise((resolve) => {
|
||||
const req = https.get('https://api.ipify.org?format=json', { timeout: 5000 }, (res) => {
|
||||
let body = '';
|
||||
res.on('data', d => { body += d; });
|
||||
res.on('end', () => {
|
||||
try { resolve(JSON.parse(body).ip || null); } catch { resolve(null); }
|
||||
});
|
||||
});
|
||||
req.on('error', () => resolve(null));
|
||||
req.on('timeout', () => { req.destroy(); resolve(null); });
|
||||
});
|
||||
if (this._externalIp) log.info('clawd', `外网 IP: ${this._externalIp}`);
|
||||
} catch (e) {
|
||||
log.warn('clawd', '外网 IP 查询失败:', e.message);
|
||||
this._externalIp = null;
|
||||
}
|
||||
|
||||
this._connect();
|
||||
}
|
||||
|
||||
@@ -266,6 +288,8 @@ class ClawClient {
|
||||
box_id: this._boxId,
|
||||
claw_id: this._cfg.claw_id ?? null,
|
||||
token: this._cfg.token ?? null,
|
||||
local_ip: getLocalIps(),
|
||||
external_ip: this._externalIp ?? null,
|
||||
...this._dashInfo,
|
||||
};
|
||||
this._send(msg);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
const { execSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const log = require('./logger');
|
||||
|
||||
const AP_SSID_PREFIX = 'ClawBox-';
|
||||
@@ -223,6 +224,29 @@ function isWifiStaConnected() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本机所有非回环 IPv4 地址,逗号拼接返回
|
||||
* 例:'192.168.1.100' 或 '192.168.1.100,10.0.0.5'
|
||||
*/
|
||||
function getLocalIps() {
|
||||
try {
|
||||
const ifaces = os.networkInterfaces();
|
||||
const ips = [];
|
||||
for (const [name, addrs] of Object.entries(ifaces)) {
|
||||
if (!addrs) continue;
|
||||
for (const addr of addrs) {
|
||||
if (addr.family === 'IPv4' && !addr.internal) {
|
||||
ips.push(addr.address);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ips.length > 0 ? ips.join(',') : null;
|
||||
} catch (e) {
|
||||
log.warn('network', '获取本机 IP 失败:', e.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
hasInternet,
|
||||
hasWiredCarrier,
|
||||
@@ -234,4 +258,5 @@ module.exports = {
|
||||
startAP,
|
||||
stopAP,
|
||||
AP_IP,
|
||||
getLocalIps,
|
||||
};
|
||||
|
||||
148
package-lock.json
generated
Normal file
148
package-lock.json
generated
Normal file
@@ -0,0 +1,148 @@
|
||||
{
|
||||
"name": "clawd",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "clawd",
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ssh2": "^1.17.0",
|
||||
"systeminformation": "^5.25.0",
|
||||
"ws": "^8.18.0"
|
||||
},
|
||||
"bin": {
|
||||
"clawd": "bin/clawd.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/asn1": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
|
||||
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"node_modules/buildcheck": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.7.tgz",
|
||||
"integrity": "sha512-lHblz4ahamxpTmnsk+MNTRWsjYKv965MwOrSJyeD588rR3Jcu7swE+0wN5F+PbL5cjgu/9ObkhfzEPuofEMwLA==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cpu-features": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz",
|
||||
"integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==",
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"buildcheck": "~0.0.6",
|
||||
"nan": "^2.19.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nan": {
|
||||
"version": "2.26.1",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.26.1.tgz",
|
||||
"integrity": "sha512-vodKprLlmaKmraa9E/TxHQwpH4eKYTJbLdeQE49pb9GOmrLs68zESjJu0LQOz1W6JwJmftOWD5Ls4dpd/elQtQ==",
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ssh2": {
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.17.0.tgz",
|
||||
"integrity": "sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"asn1": "^0.2.6",
|
||||
"bcrypt-pbkdf": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.16.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"cpu-features": "~0.0.10",
|
||||
"nan": "^2.23.0"
|
||||
}
|
||||
},
|
||||
"node_modules/systeminformation": {
|
||||
"version": "5.31.4",
|
||||
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.4.tgz",
|
||||
"integrity": "sha512-lZppDyQx91VdS5zJvAyGkmwe+Mq6xY978BDUG2wRkWE+jkmUF5ti8cvOovFQoN5bvSFKCXVkyKEaU5ec3SJiRg==",
|
||||
"license": "MIT",
|
||||
"os": [
|
||||
"darwin",
|
||||
"linux",
|
||||
"win32",
|
||||
"freebsd",
|
||||
"openbsd",
|
||||
"netbsd",
|
||||
"sunos",
|
||||
"android"
|
||||
],
|
||||
"bin": {
|
||||
"systeminformation": "lib/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "Buy me a coffee",
|
||||
"url": "https://www.buymeacoffee.com/systeminfo"
|
||||
}
|
||||
},
|
||||
"node_modules/tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.19.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
|
||||
"integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
package.json
12
package.json
@@ -9,14 +9,20 @@
|
||||
"scripts": {
|
||||
"start": "node bin/clawd.js"
|
||||
},
|
||||
"keywords": ["claw", "iot", "websocket", "daemon"],
|
||||
"keywords": [
|
||||
"claw",
|
||||
"iot",
|
||||
"websocket",
|
||||
"daemon"
|
||||
],
|
||||
"author": "stswangzhiping",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": "^8.18.0",
|
||||
"systeminformation": "^5.25.0"
|
||||
"ssh2": "^1.17.0",
|
||||
"systeminformation": "^5.25.0",
|
||||
"ws": "^8.18.0"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user