more refactor
This commit is contained in:
+11
-24
@@ -3,16 +3,7 @@ import { RemoteInfo } from "node:dgram";
|
||||
import { Commands, CommandsByValue, ControlCommands } from "./datatypes.js";
|
||||
import { XqBytesDec } from "./func_replacements.js";
|
||||
import { hexdump } from "./hexdump.js";
|
||||
import {
|
||||
create_P2pClose,
|
||||
create_P2pRdy,
|
||||
SendDevStatus,
|
||||
SendListWifi,
|
||||
SendReboot,
|
||||
SendStartVideo,
|
||||
SendUsrChk,
|
||||
SendWifiSettings,
|
||||
} from "./impl.js";
|
||||
import { create_P2pRdy, SendListWifi, SendUsrChk } from "./impl.js";
|
||||
import { Session } from "./session.js";
|
||||
import { u16_swap, u32_swap } from "./utils.js";
|
||||
|
||||
@@ -53,14 +44,14 @@ export const handle_PunchPkt = (session: Session, dv: DataView, rinfo: RemoteInf
|
||||
session.send(create_P2pRdy(dv.add(4).readByteArray(len)));
|
||||
};
|
||||
|
||||
export const createResponseForControlCommand = (session: Session, dv: DataView): DataView | undefined => {
|
||||
export const createResponseForControlCommand = (session: Session, dv: DataView): DataView[] => {
|
||||
const start_type = dv.add(8).readU16(); // 0xa11 on control; data starts here on DATA pkt
|
||||
const cmd_id = dv.add(10).readU16(); // 0x1120
|
||||
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)}`);
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
const rotate_chr = 4;
|
||||
if (payload_len > rotate_chr) {
|
||||
@@ -73,11 +64,12 @@ export const createResponseForControlCommand = (session: Session, dv: DataView):
|
||||
if (cmd_id == ControlCommands.ConnectUserAck) {
|
||||
let c = new Uint8Array(dv.add(0x18).readByteArray(4).buffer);
|
||||
session.ticket = [...c];
|
||||
const buf = SendStartVideo(session);
|
||||
return buf;
|
||||
session.eventEmitter.emit("login");
|
||||
return [];
|
||||
}
|
||||
|
||||
if (cmd_id == ControlCommands.DevStatusAck) {
|
||||
// ParseDevStatus -> offset relevant?
|
||||
let charging = u32_swap(dv.add(0x28).readU32()) & 1; // 0x14000101 v 0x14000100
|
||||
let power = u16_swap(dv.add(0x18).readU16()); // '3730' or '3765', milliVolts?
|
||||
let dbm = dv.add(0x24).readU8() - 0x100; // 0xbf - 0x100 = -65dbm .. constant??
|
||||
@@ -104,12 +96,7 @@ export const createResponseForControlCommand = (session: Session, dv: DataView):
|
||||
};
|
||||
const buf = SendListWifi(session);
|
||||
console.log(`Current wifi settings: ${JSON.stringify(wifiSettings, null, 2)}`);
|
||||
setTimeout(() => {
|
||||
console.log("send now??");
|
||||
const buf = SendListWifi(session);
|
||||
session.send(buf);
|
||||
}, 8000);
|
||||
return buf;
|
||||
return [buf];
|
||||
}
|
||||
|
||||
if (cmd_id == ControlCommands.ListWifiAck) {
|
||||
@@ -138,6 +125,7 @@ export const createResponseForControlCommand = (session: Session, dv: DataView):
|
||||
items.push(wifiListItem);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
let seq = 0;
|
||||
@@ -184,7 +172,8 @@ const deal_with_data = (session: Session, dv: DataView) => {
|
||||
return;
|
||||
}
|
||||
if (pkt_id > seq + 1) {
|
||||
// missed some packets -- filling with zeroes still produces a broken image
|
||||
// missed some packets -- filling with zeroes still produces a broken
|
||||
// image
|
||||
frame_is_bad = true;
|
||||
return;
|
||||
}
|
||||
@@ -221,8 +210,6 @@ export const handle_Drw = (session: Session, dv: DataView) => {
|
||||
deal_with_data(session, dv);
|
||||
} else {
|
||||
const b = createResponseForControlCommand(session, dv);
|
||||
if (b != undefined) {
|
||||
session.send(b);
|
||||
}
|
||||
b.forEach(session.send);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -43,6 +43,7 @@ const makeDataReadWrite = (session: Session, command: number, data: DataView | n
|
||||
ret.add(20).writeByteArray(bufCopy);
|
||||
}
|
||||
|
||||
session.outgoingCommandId++;
|
||||
return ret;
|
||||
};
|
||||
|
||||
@@ -76,7 +77,7 @@ export const getVideoKey = (session: Session): void => {
|
||||
}
|
||||
};
|
||||
|
||||
export const SendVideoResolution = (session: Session, resol: 1 | 2 | 3 | 4): null => {
|
||||
export const SendVideoResolution = (session: Session, resol: 1 | 2 | 3 | 4): DataView[] => {
|
||||
// seems like 0x1 = resolution, and is specified by ID not by size
|
||||
// unclear what 0x2-0xf achieve - they report back as '0' always -- ignored?
|
||||
const pairs = {
|
||||
@@ -103,11 +104,10 @@ export const SendVideoResolution = (session: Session, resol: 1 | 2 | 3 | 4): nul
|
||||
// maybe the 0x7 = bitrate??
|
||||
};
|
||||
|
||||
pairs[resol].forEach((payload: number[]) => {
|
||||
return pairs[resol].map((payload: number[]) => {
|
||||
const dv = new DataView(new Uint8Array(payload).buffer);
|
||||
session.send(makeDataReadWrite(session, ControlCommands.VideoParamSet, dv));
|
||||
return makeDataReadWrite(session, ControlCommands.VideoParamSet, dv);
|
||||
});
|
||||
return null;
|
||||
};
|
||||
|
||||
export const SendReboot = (session: Session): DataView => {
|
||||
|
||||
+16
-3
@@ -4,6 +4,7 @@ import { Commands, CommandsByValue } from "./datatypes.js";
|
||||
import { handle_P2PAlive, handle_PunchPkt, handle_P2PRdy, handle_Drw, notImpl, noop } from "./handlers.js";
|
||||
import { hexdump } from "./hexdump.js";
|
||||
import EventEmitter from "node:events";
|
||||
import { SendVideoResolution, SendStartVideo, SendWifiDetails } from "./impl.js";
|
||||
|
||||
export type Session = {
|
||||
send: (msg: DataView) => void;
|
||||
@@ -14,6 +15,7 @@ export type Session = {
|
||||
dst_ip: string;
|
||||
lastReceivedPacket: number;
|
||||
connected: boolean;
|
||||
devName: string;
|
||||
timers: ReturnType<typeof setInterval>[];
|
||||
};
|
||||
|
||||
@@ -82,6 +84,7 @@ export const makeSession = (handlers: Record<keyof typeof Commands, PacketHandle
|
||||
eventEmitter: new EventEmitter(),
|
||||
connected: false,
|
||||
timers: [],
|
||||
devName: "",
|
||||
send: (msg: DataView) => {
|
||||
const raw = msg.readU16();
|
||||
const cmd = CommandsByValue[raw];
|
||||
@@ -91,9 +94,6 @@ export const makeSession = (handlers: Record<keyof typeof Commands, PacketHandle
|
||||
console.log(hexdump(msg.buffer, { ansi: options.ansi, ansiColor: 0 }));
|
||||
}
|
||||
}
|
||||
if (raw == Commands.Drw) {
|
||||
session.outgoingCommandId++;
|
||||
}
|
||||
sock.send(new Uint8Array(msg.buffer), SEND_PORT, session.dst_ip);
|
||||
},
|
||||
broadcast: (msg: DataView) => {
|
||||
@@ -115,6 +115,7 @@ export const makeSession = (handlers: Record<keyof typeof Commands, PacketHandle
|
||||
session.outgoingCommandId = 0;
|
||||
session.dst_ip = rinfo.address;
|
||||
session.connected = true;
|
||||
session.devName = name;
|
||||
|
||||
const int = setInterval(() => {
|
||||
const delta = Date.now() - session.lastReceivedPacket;
|
||||
@@ -128,9 +129,21 @@ export const makeSession = (handlers: Record<keyof typeof Commands, PacketHandle
|
||||
}, 400);
|
||||
session.timers.push(int);
|
||||
});
|
||||
|
||||
session.eventEmitter.on("login", () => {
|
||||
console.log(`Logged in - ${session.devName}`);
|
||||
startVideoStream(session);
|
||||
});
|
||||
return session;
|
||||
};
|
||||
|
||||
const startVideoStream = (s: Session) => {
|
||||
[
|
||||
...SendVideoResolution(s, 2), // 640x480
|
||||
SendStartVideo(s),
|
||||
].forEach(s.send);
|
||||
};
|
||||
|
||||
export const Handlers: Record<keyof typeof Commands, PacketHandler> = {
|
||||
PunchPkt: handle_PunchPkt,
|
||||
P2PAlive: handle_P2PAlive,
|
||||
|
||||
+9
-8
@@ -5,7 +5,7 @@ import assert from "assert";
|
||||
import { XqBytesDec, XqBytesEnc } from "../func_replacements.js";
|
||||
import { createResponseForControlCommand } from "../handlers.js";
|
||||
import { hexdump } from "../hexdump.js";
|
||||
import { SendDevStatus, SendUsrChk, SendWifiDetails } from "../impl.ts";
|
||||
import { SendStartVideo, SendDevStatus, SendUsrChk, SendWifiDetails } from "../impl.ts";
|
||||
import { placeholderTypes, sprintf } from "../utils.js";
|
||||
|
||||
describe("debug_tools", () => {
|
||||
@@ -123,6 +123,11 @@ describe("module", () => {
|
||||
});
|
||||
|
||||
const hstrToBA = (hs) => new Uint8Array(hs.match(/../g).map((h) => parseInt(h, 16))).buffer;
|
||||
describe("events", () => {
|
||||
it("emits login event upon logging in", () => {
|
||||
// TODO
|
||||
});
|
||||
});
|
||||
describe("make packet", () => {
|
||||
it("builds a good SendUsrChk", () => {
|
||||
const expected_str =
|
||||
@@ -132,16 +137,12 @@ describe("make packet", () => {
|
||||
assert.deepEqual(SendUsrChk(sess, "admin", "admin").buffer, expected);
|
||||
});
|
||||
it("builds a good SendStartVideo", () => {
|
||||
const input_pkt_str = "f1d00018d1000000110a20110c00ff000000000064504737fe010101";
|
||||
// token-in = 0x64 0x50 0x47 0x37
|
||||
const _expected_str = "f1d00010d1000000110a10300400000065514636";
|
||||
// output is 0x3010; 'start video'; hardcoded but shouldnt
|
||||
const _expected_str = "f1d00010d1000000110a10300400000001020304";
|
||||
const expected = hstrToBA(_expected_str);
|
||||
|
||||
const sess = { outgoingCommandId: 0, ticket: [0, 0, 0, 0] };
|
||||
const got = createResponseForControlCommand(sess, new DataView(hstrToBA(input_pkt_str)));
|
||||
const sess = { outgoingCommandId: 0, ticket: [1, 2, 3, 4] };
|
||||
const got = SendStartVideo(sess);
|
||||
assert.deepEqual(got.buffer, expected);
|
||||
assert.deepEqual(sess.ticket, [0x65, 0x51, 0x46, 0x36]);
|
||||
});
|
||||
it("builds a good SendDevStatus", () => {
|
||||
const sess = { outgoingCommandId: 0, ticket: [1, 2, 3, 4] };
|
||||
|
||||
Reference in New Issue
Block a user