implement logging properly

This commit is contained in:
David Ventura
2024-05-01 13:06:27 +02:00
parent 9c19c05274
commit 9654dc2841
12 changed files with 339 additions and 90 deletions
+5 -4
View File
@@ -1,4 +1,4 @@
.PHONY: run hook install-wireshark-dissector test build
.PHONY: run hook install-wireshark-dissector test build typecheck
bundle.js: frida-hooks.js func_replacements.js
~/node_modules/.bin/frida-compile -o $@ frida-hooks.js
@@ -8,12 +8,13 @@ venv: requirements.txt
./venv/bin/pip install -r requirements.txt
touch venv
build: node_modules
typecheck: node_modules
npm run tsc
build: node_modules
npm run build
run: node_modules
./node_modules/.bin/ts-node --esm cmd/bin.ts http_server --port=1234
run: build
node dist/bin.cjs http_server --port=1234
hook: bundle.js venv
./venv/bin/python3 -u loader3.py
+4 -15
View File
@@ -32,17 +32,6 @@
audio_button.disabled = !${audio};
update_audio_button();
function console_log(s) {
if (!${debug}) {
return;
}
let m = "";
for (let i = 0; i < arguments.length; i++) {
m += arguments[i];
}
console.log(m);
}
function setup_audio() {
audio_context = new AudioContext();
const gain_node = audio_context.createGain(); // Declare gain node
@@ -52,7 +41,7 @@
//const audioBuffer = audio_context.createBuffer(channels, decoded.length, sample_rate);
audio_context.onstatechange = () => {
console_log("Audio state is now ", audio_context.state);
console.log("Audio state is now ", audio_context.state);
update_audio_button(audio_context.state == "running");
};
@@ -62,10 +51,10 @@
const evtSource = new EventSource("/audio/${id}");
if (${debug}) {
evtSource.onopen = (e) => {
console_log("evtsource open");
console.log("evtsource open");
}
evtSource.onerror = (e) => {
console_log("evtsource error", e);
console.log("evtsource error", e);
}
}
let endsAt = 0;
@@ -108,7 +97,7 @@
audio_context.resume();
return;
}
console_log("Unknown audio stream status");
console.log("Unknown audio stream status");
}
</script>
</html>
+10 -4
View File
@@ -5,17 +5,20 @@ import { serveHttp } from "../http_server.js";
import { opt } from "../options.js";
import { pair } from "../pair.js";
import { buildLogger } from "../logger.js";
yargs(hideBin(process.argv))
.command(
"http_server",
"start http server",
(yargs) => {
return yargs
.option("debug", { describe: "Log debug messages", default: false })
.option("ansi", { default: false })
.option("slow_startup", { default: false })
.option("audio", { describe: "Also stream audio from camera", default: true })
.boolean(["debug", "ansi", "audio", "slow_startup"])
.option("color", { describe: "Use color in logs", default: undefined })
.boolean(["ansi", "audio", "slow_startup", "color"])
.option("log_level", { describe: "Set log level", default: "info" })
.option("discovery_ip", { describe: "Camera discovery IP address", default: "192.168.1.255" })
.option("attempt_to_fix_packet_loss", { default: false })
.option("port", { describe: "HTTP Port to listen on", default: 5000 })
@@ -24,6 +27,7 @@ yargs(hideBin(process.argv))
},
(argv) => {
const opts: opt = argv as opt;
buildLogger(argv.log_level, argv.color);
serveHttp(opts, argv.port, argv.audio || false);
},
)
@@ -32,10 +36,11 @@ yargs(hideBin(process.argv))
"configure a camera",
(yargs) => {
return yargs
.option("debug", { describe: "Log debug messages", default: false })
.option("ansi", { default: false })
.option("slow_startup", { default: false })
.boolean(["debug", "ansi", "slow_startup"])
.option("color", { describe: "Use color in logs", default: undefined })
.boolean(["ansi", "slow_startup", "color"])
.option("log_level", { describe: "Set log level", default: "info" })
.option("discovery_ip", { describe: "Camera discovery IP address", default: "192.168.1.255" })
.option("attempt_to_fix_packet_loss", { default: false })
.option("ssid", { describe: "Wifi network for the camera to connect to" })
@@ -45,6 +50,7 @@ yargs(hideBin(process.argv))
},
(argv) => {
const opts: opt = argv as unknown as opt;
buildLogger(argv.log_level, argv.color);
pair({ opts, ssid: argv.ssid, password: argv.password });
},
)
+6 -8
View File
@@ -2,21 +2,20 @@ import EventEmitter from "node:events";
import { create_LanSearch, parse_PunchPkt } from "./impl.js";
import { createSocket, RemoteInfo } from "node:dgram";
import { Commands } from "./datatypes.js";
import { logger } from "./logger.js";
const handleIncomingPunch = (msg: Buffer, ee: EventEmitter, rinfo: RemoteInfo, debug: boolean) => {
const handleIncomingPunch = (msg: Buffer, ee: EventEmitter, rinfo: RemoteInfo) => {
const ab = new Uint8Array(msg).buffer;
const dv = new DataView(ab);
const cmd_id = dv.readU16();
if (cmd_id != Commands.PunchPkt) {
return;
}
if (debug) {
console.log("Discovery got a PunchPkt");
}
logger.debug("Received a PunchPkt message");
ee.emit("discover", rinfo, parse_PunchPkt(dv));
};
export const discoverDevices = (debug: boolean, discovery_ip: string): EventEmitter => {
export const discoverDevices = (discovery_ip: string): EventEmitter => {
const sock = createSocket("udp4");
const SEND_PORT = 32108;
const ee = new EventEmitter();
@@ -26,15 +25,14 @@ export const discoverDevices = (debug: boolean, discovery_ip: string): EventEmit
sock.close();
});
sock.on("message", (msg, rinfo) => handleIncomingPunch(msg, ee, rinfo, debug));
sock.on("message", (msg, rinfo) => handleIncomingPunch(msg, ee, rinfo));
sock.on("listening", () => {
sock.setBroadcast(true);
console.log(`Searching for devices on ${discovery_ip}`);
logger.info(`Searching for devices on ${discovery_ip}`);
let buf = create_LanSearch();
setInterval(() => {
process.stdout.write(".");
sock.send(new Uint8Array(buf.buffer), SEND_PORT, discovery_ip);
}, 2000);
sock.send(new Uint8Array(buf.buffer), SEND_PORT, discovery_ip);
+9 -21
View File
@@ -1,16 +1,14 @@
import { Commands, CommandsByValue, ControlCommands } from "./datatypes.js";
import { XqBytesDec } from "./func_replacements.js";
import { hexdump } from "./hexdump.js";
import { create_P2pRdy, SendListWifi, SendUsrChk, DevSerial } from "./impl.js";
import { Session } from "./session.js";
import { u16_swap, u32_swap } from "./utils.js";
import { logger } from "./logger.js";
export const notImpl = (session: Session, dv: DataView) => {
const raw = dv.readU16();
const cmd = CommandsByValue[raw];
if (session.options.debug) {
console.log(`^^ ${cmd} (${raw.toString(16)}) and it's not implemented yet`);
}
logger.debug(`^^ ${cmd} (${raw.toString(16)}) and it's not implemented yet`);
};
export const noop = (_: Session, __: DataView) => {};
@@ -47,17 +45,13 @@ export const createResponseForControlCommand = (session: Session, dv: DataView):
const payload_len = u16_swap(dv.add(0xc).readU16());
if (start_type != 0x110a) {
console.error(`Expected start_type to be 0xa11, got 0x${start_type.toString(16)}`);
logger.error(`Expected start_type to be 0xa11, got 0x${start_type.toString(16)}`);
return [];
}
const rotate_chr = 4;
if (payload_len > rotate_chr) {
// 20 = 16 (header) + 4 (??)
XqBytesDec(dv.add(20), payload_len - 4, rotate_chr);
if (session.options.debug) {
console.log("Decrypted");
console.log(hexdump(dv));
}
}
if (cmd_id == ControlCommands.ConnectUserAck) {
@@ -74,7 +68,7 @@ export const createResponseForControlCommand = (session: Session, dv: DataView):
let dbm = dv.add(0x24).readU8() - 0x100; // 0xbf - 0x100 = -65dbm .. constant??
// > -50 = excellent, -50 to -60 good, -60 to -70 fair, <-70 weak
console.log(`Camera ${session.devName}: ${charging}charging, battery at ${power / 1000}V, Wifi ${dbm} dBm`);
logger.info(`Camera ${session.devName}: ${charging}charging, battery at ${power / 1000}V, Wifi ${dbm} dBm`);
}
if (cmd_id == ControlCommands.WifiSettingsAck) {
@@ -94,21 +88,17 @@ export const createResponseForControlCommand = (session: Session, dv: DataView):
dns2: dv.add(0x10c).readString(0x10),
};
const buf = SendListWifi(session);
console.log(`Current Wifi settings: ${JSON.stringify(wifiSettings, null, 2)}`);
logger.info(`Current Wifi settings: ${JSON.stringify(wifiSettings, null, 2)}`);
return [buf];
}
if (cmd_id == ControlCommands.ListWifiAck) {
let startat = 0x10;
let msg_len = 91;
if (session.options.debug) {
console.log("payload len", payload_len);
}
logger.debug("payload len", payload_len);
let msg_count = (payload_len - 9) / msg_len;
let remote_msg_count = dv.add(startat).readU32LE();
if (session.options.debug) {
console.log("should get messages:", msg_count, "in payload: ", remote_msg_count);
}
logger.debug("should get messages:", msg_count, "in payload: ", remote_msg_count);
startat += 4;
let items = [];
for (let i = 0; i < msg_count; i++) {
@@ -122,11 +112,9 @@ export const createResponseForControlCommand = (session: Session, dv: DataView):
mode: dv.add(startat + 0x54).readU32LE(),
channel: dv.add(startat + 0x58).readU32LE(),
};
console.log(`Wifi Item: ${JSON.stringify(wifiListItem, null, 2)}`);
logger.info(`Wifi Item: ${JSON.stringify(wifiListItem, null, 2)}`);
startat += msg_len;
if (session.options.debug) {
console.log("ended at", startat);
}
logger.debug("ended at", startat);
items.push(wifiListItem);
}
}
+11 -10
View File
@@ -2,6 +2,7 @@ import { RemoteInfo } from "dgram";
import { readFileSync, existsSync } from "node:fs";
import http from "node:http";
import { logger } from "./logger.js";
import { opt } from "./options.js";
import { discoverDevices } from "./discovery.js";
import { DevSerial, SendDevStatus } from "./impl.js";
@@ -77,7 +78,7 @@ export const serveHttp = (opts: opt, port: number, with_audio: boolean) => {
}
res.setHeader("Content-Type", `text/event-stream`);
audioResponses[devId].push(res);
console.log(`Audio stream requested for camera ${devId}`);
logger.info(`Audio stream requested for camera ${devId}`);
return;
}
@@ -90,7 +91,7 @@ export const serveHttp = (opts: opt, port: number, with_audio: boolean) => {
if (req.url.startsWith("/camera/")) {
let devId = req.url.split("/")[2];
console.log(`Video stream requested for camera ${devId}`);
logger.info(`Video stream requested for camera ${devId}`);
let s = sessions[devId];
if (s === undefined) {
@@ -108,7 +109,7 @@ export const serveHttp = (opts: opt, port: number, with_audio: boolean) => {
responses[devId].push(res);
res.on("close", () => {
responses[devId] = responses[devId].filter((r) => r !== res);
console.log(`Video stream closed for camera ${devId}`);
logger.info(`Video stream closed for camera ${devId}`);
});
} else {
res.write("<html>");
@@ -127,21 +128,21 @@ export const serveHttp = (opts: opt, port: number, with_audio: boolean) => {
}
});
let devEv = discoverDevices(opts.debug, opts.discovery_ip);
let devEv = discoverDevices(opts.discovery_ip);
const startSession = (s: Session) => {
s.send(SendDevStatus(s));
startVideoStream(s);
console.log(`Camera ${s.devName} is now ready to stream`);
}
logger.info(`Camera ${s.devName} is now ready to stream`);
};
devEv.on("discover", (rinfo: RemoteInfo, dev: DevSerial) => {
if (dev.devId in sessions) {
console.log(`Camera ${dev.devId} at ${rinfo.address} already discovered, ignoring`);
logger.info(`Camera ${dev.devId} at ${rinfo.address} already discovered, ignoring`);
return;
}
console.log(`Discovered camera ${dev.devId} at ${rinfo.address}`);
logger.info(`Discovered camera ${dev.devId} at ${rinfo.address}`);
responses[dev.devId] = [];
audioResponses[dev.devId] = [];
const s = makeSession(Handlers, dev, rinfo, startSession, opts);
@@ -158,7 +159,7 @@ export const serveHttp = (opts: opt, port: number, with_audio: boolean) => {
});
s.eventEmitter.on("disconnect", () => {
console.log(`Camera ${dev.devId} disconnected`);
logger.info(`Camera ${dev.devId} disconnected`);
delete sessions[dev.devId];
});
if (with_audio) {
@@ -175,6 +176,6 @@ export const serveHttp = (opts: opt, port: number, with_audio: boolean) => {
sessions[dev.devId] = s;
});
console.log(`Starting HTTP server on port ${port}`);
logger.info(`Starting HTTP server on port ${port}`);
server.listen(port);
};
+26
View File
@@ -0,0 +1,26 @@
import { isatty } from "node:tty";
import { addColors, config, createLogger, format, transports as wtransports } from "winston";
const myFormat = format.printf(({ level, message, timestamp }) => {
return `${timestamp} [${level}] ${message}`;
});
const transports = {
console: new wtransports.Console(),
};
export let logger = undefined;
export const buildLogger = (level: string, colorize: boolean | undefined) => {
let use_color = colorize === undefined ? isatty(1) : colorize;
const fmt = use_color
? format.combine(format.colorize(), format.timestamp(), myFormat)
: format.combine(format.timestamp(), myFormat);
logger = createLogger({
levels: { ...config.syslog.levels, trace: 10 },
level,
format: fmt,
transports: [transports.console],
});
addColors({ trace: "white" });
};
-1
View File
@@ -1,5 +1,4 @@
export type opt = {
debug: boolean;
ansi: boolean;
discovery_ip: string;
slow_startup: boolean;
+253 -6
View File
@@ -5,16 +5,25 @@
"packages": {
"": {
"dependencies": {
"esbuild": "^0.20.2",
"winston": "^3.13.0",
"yargs": "^17.7.2"
},
"devDependencies": {
"@types/yargs": "^17.0.32",
"esbuild": "^0.20.2",
"mocha": "^10.2.0",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
}
},
"node_modules/@colors/colors": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
"integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
"engines": {
"node": ">=0.1.90"
}
},
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
@@ -27,6 +36,16 @@
"node": ">=12"
}
},
"node_modules/@dabh/diagnostics": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz",
"integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==",
"dependencies": {
"colorspace": "1.1.x",
"enabled": "2.0.x",
"kuler": "^2.0.0"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
@@ -34,6 +53,7 @@
"cpu": [
"ppc64"
],
"dev": true,
"optional": true,
"os": [
"aix"
@@ -49,6 +69,7 @@
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"android"
@@ -64,6 +85,7 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"android"
@@ -79,6 +101,7 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"android"
@@ -94,6 +117,7 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
@@ -109,6 +133,7 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
@@ -124,6 +149,7 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
@@ -139,6 +165,7 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
@@ -154,6 +181,7 @@
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"linux"
@@ -169,6 +197,7 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@@ -184,6 +213,7 @@
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"linux"
@@ -199,6 +229,7 @@
"cpu": [
"loong64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@@ -214,6 +245,7 @@
"cpu": [
"mips64el"
],
"dev": true,
"optional": true,
"os": [
"linux"
@@ -229,6 +261,7 @@
"cpu": [
"ppc64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@@ -244,6 +277,7 @@
"cpu": [
"riscv64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@@ -259,6 +293,7 @@
"cpu": [
"s390x"
],
"dev": true,
"optional": true,
"os": [
"linux"
@@ -274,6 +309,7 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@@ -289,6 +325,7 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"netbsd"
@@ -304,6 +341,7 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"openbsd"
@@ -319,6 +357,7 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"sunos"
@@ -334,6 +373,7 @@
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"win32"
@@ -349,6 +389,7 @@
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"win32"
@@ -364,6 +405,7 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"win32"
@@ -431,6 +473,11 @@
"undici-types": "~5.26.4"
}
},
"node_modules/@types/triple-beam": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
"integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="
},
"node_modules/@types/yargs": {
"version": "17.0.32",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz",
@@ -523,6 +570,11 @@
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
},
"node_modules/async": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
"integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg=="
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -645,6 +697,15 @@
"node": ">=12"
}
},
"node_modules/color": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
"integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
"dependencies": {
"color-convert": "^1.9.3",
"color-string": "^1.6.0"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -661,6 +722,37 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/color-string": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"node_modules/color/node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dependencies": {
"color-name": "1.1.3"
}
},
"node_modules/color/node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
},
"node_modules/colorspace": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
"integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
"dependencies": {
"color": "^3.1.3",
"text-hex": "1.0.x"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -722,10 +814,16 @@
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/enabled": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
"integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="
},
"node_modules/esbuild": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
"integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
"dev": true,
"hasInstallScript": true,
"bin": {
"esbuild": "bin/esbuild"
@@ -779,6 +877,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/fecha": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
"integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="
},
"node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -816,6 +919,11 @@
"flat": "cli.js"
}
},
"node_modules/fn.name": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -929,8 +1037,12 @@
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
},
"node_modules/is-binary-path": {
"version": "2.1.0",
@@ -991,6 +1103,17 @@
"node": ">=8"
}
},
"node_modules/is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
@@ -1015,6 +1138,11 @@
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/kuler": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
"integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
},
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -1046,6 +1174,22 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/logform": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz",
"integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==",
"dependencies": {
"@colors/colors": "1.6.0",
"@types/triple-beam": "^1.3.2",
"fecha": "^4.2.0",
"ms": "^2.1.1",
"safe-stable-stringify": "^2.3.1",
"triple-beam": "^1.3.0"
},
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
@@ -1136,8 +1280,7 @@
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/nanoid": {
"version": "3.3.3",
@@ -1169,6 +1312,14 @@
"wrappy": "1"
}
},
"node_modules/one-time": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
"integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
"dependencies": {
"fn.name": "1.x.x"
}
},
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -1238,6 +1389,19 @@
"safe-buffer": "^5.1.0"
}
},
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
@@ -1262,7 +1426,6 @@
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true,
"funding": [
{
"type": "github",
@@ -1278,6 +1441,14 @@
}
]
},
"node_modules/safe-stable-stringify": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz",
"integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==",
"engines": {
"node": ">=10"
}
},
"node_modules/serialize-javascript": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
@@ -1287,6 +1458,30 @@
"randombytes": "^2.1.0"
}
},
"node_modules/simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"dependencies": {
"is-arrayish": "^0.3.1"
}
},
"node_modules/stack-trace": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
"integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
"engines": {
"node": "*"
}
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"dependencies": {
"safe-buffer": "~5.2.0"
}
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
@@ -1338,6 +1533,11 @@
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
"node_modules/text-hex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -1350,6 +1550,14 @@
"node": ">=8.0"
}
},
"node_modules/triple-beam": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
"integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==",
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/ts-node": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
@@ -1422,12 +1630,51 @@
"dev": true,
"peer": true
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true
},
"node_modules/winston": {
"version": "3.13.0",
"resolved": "https://registry.npmjs.org/winston/-/winston-3.13.0.tgz",
"integrity": "sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==",
"dependencies": {
"@colors/colors": "^1.6.0",
"@dabh/diagnostics": "^2.0.2",
"async": "^3.2.3",
"is-stream": "^2.0.0",
"logform": "^2.4.0",
"one-time": "^1.0.0",
"readable-stream": "^3.4.0",
"safe-stable-stringify": "^2.3.1",
"stack-trace": "0.0.x",
"triple-beam": "^1.3.0",
"winston-transport": "^4.7.0"
},
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/winston-transport": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz",
"integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==",
"dependencies": {
"logform": "^2.3.2",
"readable-stream": "^3.6.0",
"triple-beam": "^1.3.0"
},
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/workerpool": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+1
View File
@@ -13,6 +13,7 @@
"typescript": "^5.3.3"
},
"dependencies": {
"winston": "^3.13.0",
"yargs": "^17.7.2"
}
}
+9 -8
View File
@@ -4,32 +4,33 @@ import { opt } from "./options.js";
import { discoverDevices } from "./discovery.js";
import { DevSerial } from "./impl.js";
import { Handlers, makeSession, Session, configureWifi } from "./session.js";
import { logger } from "./logger.js";
export const pair = ({ opts, ssid, password }: { opts: opt; ssid: string; password: string }) => {
console.log(`Will configure any devices found to join ${ssid}`);
logger.info(`Will configure any devices found to join ${ssid}`);
let sessions: Record<string, Session> = {};
let devEv = discoverDevices(opts.debug, opts.discovery_ip);
let devEv = discoverDevices(opts.discovery_ip);
if (password == "") {
throw new Error("You must set a non-zero-length password");
}
const onLogin = (s: Session) => {
configureWifi(ssid, password)(s);
console.log(`WiFi config for camera ${s.devName} is done`);
}
logger.info(`WiFi config for camera ${s.devName} is done`);
};
devEv.on("discover", (rinfo: RemoteInfo, dev: DevSerial) => {
if (dev.devId in sessions) {
console.log(`Camera ${dev.devId} at ${rinfo.address} already discovered, ignoring`);
logger.info(`Camera ${dev.devId} at ${rinfo.address} already discovered, ignoring`);
return;
}
console.log(`Discovered camera ${dev.devId} at ${rinfo.address}`);
logger.info(`Discovered camera ${dev.devId} at ${rinfo.address}`);
const s = makeSession(Handlers, dev, rinfo, onLogin, opts);
s.eventEmitter.on("disconnect", () => {
console.log(`Camera ${dev.devId} disconnected`);
console.log("Press CONTROL+C if you're done setting up your cameras");
logger.info(`Camera ${dev.devId} disconnected`);
logger.info("Press CONTROL+C if you're done setting up your cameras");
delete sessions[dev.devId];
});
sessions[dev.devId] = s;
+5 -13
View File
@@ -3,9 +3,9 @@ import EventEmitter from "node:events";
import { Commands, CommandsByValue } from "./datatypes.js";
import { handle_Drw, handle_P2PAlive, handle_P2PRdy, makeP2pRdy, noop, notImpl } from "./handlers.js";
import { hexdump } from "./hexdump.js";
import { create_P2pAlive, DevSerial, SendStartVideo, SendVideoResolution, SendWifiDetails } from "./impl.js";
import { opt } from "./options.js";
import { logger } from "./logger.js";
export type Session = {
send: (msg: DataView) => void;
@@ -38,10 +38,7 @@ const handleIncoming: msgCb = (session, handlers, msg, rinfo) => {
const ab = new Uint8Array(msg).buffer;
const dv = new DataView(ab);
const cmd = CommandsByValue[dv.readU16()];
if (session.options.debug) {
console.log(`<< ${cmd}`);
console.log(hexdump(msg.buffer, { ansi: session.options.ansi, ansiColor: 1 }));
}
logger.log("trace", `<< ${cmd}`);
handlers[cmd](session, dv, rinfo);
session.lastReceivedPacket = Date.now();
};
@@ -105,12 +102,7 @@ export const makeSession = (
send: (msg: DataView) => {
const raw = msg.readU16();
const cmd = CommandsByValue[raw];
if (options.debug) {
console.log(`>> ${cmd}`);
if (raw != Commands.P2PAlive) {
console.log(hexdump(msg.buffer, { ansi: options.ansi, ansiColor: 0 }));
}
}
logger.log("trace", `>> ${cmd}`);
sock.send(new Uint8Array(msg.buffer), SEND_PORT, session.dst_ip);
},
dst_ip: ra.address,
@@ -122,7 +114,7 @@ export const makeSession = (
};
session.eventEmitter.on("disconnect", () => {
console.log(`Disconnected from camera ${session.devName} at ${session.dst_ip}`);
logger.info(`Disconnected from camera ${session.devName} at ${session.dst_ip}`);
session.dst_ip = "0.0.0.0";
session.connected = false;
session.timers.forEach((x) => clearInterval(x));
@@ -130,7 +122,7 @@ export const makeSession = (
});
session.eventEmitter.on("login", () => {
console.log(`Logging in to camera ${session.devName}`);
logger.info(`Logging in to camera ${session.devName}`);
onLogin(session);
});
return session;