diff --git a/handlers.ts b/handlers.ts index 663bf0a..f63699e 100644 --- a/handlers.ts +++ b/handlers.ts @@ -42,7 +42,7 @@ export const makeP2pRdy = (dev: DevSerial): DataView => { return create_P2pRdy(outbuf); }; -const swVerToString = (swver: number): string => { +export const swVerToString = (swver: number): string => { return ( ((swver >> 24) & 255).toString() + "." + @@ -53,6 +53,25 @@ const swVerToString = (swver: number): string => { (swver & 255).toString() ); }; +export type DevStatus = { + charging: boolean; + battery_mV: number; + dbm: number; + swver: string; +}; +export const parseDevStatusAck = (dv: DataView): DevStatus => { + const charging = dv.add(0x28).readU32LE() & 1; // 0x14000101 v 0x14000100 + const power = dv.add(0x18).readU16LE(); // '3730' or '3765', milliVolts + const dbm = dv.add(0x24).readU8() - 0x100; // 0xbf - 0x100 = -65dbm .. constant?? + const n_swver = dv.add(0x14).readU32LE(); + const swver = swVerToString(n_swver); + return { + charging: charging > 0, + battery_mV: power, + dbm, + swver, + }; +}; 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 @@ -83,16 +102,13 @@ export const createResponseForControlCommand = (session: Session, dv: DataView): case ControlCommands.DevStatusAck: // ParseDevStatus -> offset relevant? - const charging = dv.add(0x28).readU32LE() & 1 ? "" : "not "; // 0x14000101 v 0x14000100 - const power = dv.add(0x18).readU16LE(); // '3730' or '3765', milliVolts - const dbm = dv.add(0x24).readU8() - 0x100; // 0xbf - 0x100 = -65dbm .. constant?? - const n_swver = dv.add(0x14).readU32LE(); - const swver = swVerToString(n_swver); - + const status = parseDevStatusAck(dv); // > -50 = excellent, -50 to -60 good, -60 to -70 fair, <-70 weak logger.info( - `Camera ${session.devName}: sw: ${swver}, ${charging}charging, battery at ${power / 1000}V, Wifi ${dbm} dBm`, + `Camera ${session.devName}: sw: ${status.swver}, ${status.charging ? "" : "not "}charging, battery at ${ + status.battery_mV + }mV, Wifi ${status.dbm} dBm`, ); return []; diff --git a/tests/fn.test.js b/tests/fn.test.js index 7d7d39c..5e9f374 100644 --- a/tests/fn.test.js +++ b/tests/fn.test.js @@ -3,9 +3,9 @@ import "../shim.ts"; import assert from "assert"; -import { hexdump } from "../hexdump.js"; import { XqBytesDec, XqBytesEnc } from "../func_replacements.js"; -import { makeP2pRdy, parseListWifi } from "../handlers.js"; +import { makeP2pRdy, parseDevStatusAck, parseListWifi } from "../handlers.js"; +import { hexdump } from "../hexdump.js"; import { parse_PunchPkt, SendDevStatus, SendStartVideo, SendUsrChk, SendWifiDetails } from "../impl.ts"; import { buildLogger } from "../logger.js"; import { placeholderTypes, sprintf } from "../utils.js"; @@ -272,4 +272,22 @@ describe("make packet", () => { const got = SendWifiDetails(sess, "ACRC.NET", "fakepass", 2, true); assert.deepEqual(got.buffer, expected); }); + it("parses devstatusack", () => { + const pkt = new DataView( + hstrToBA( + "f1d0008cd1000009110a08118000000000000000190e010101010101fefefefebefefefe01000001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100010101010001030101010101010101010101010101fefefefefe010101010101010134030300", + ), + ); + let payload_len = pkt.add(0xc).readU16LE(); + XqBytesDec(pkt.add(20), payload_len - 4, 0); // this mutates pkt + const got = parseDevStatusAck(pkt); + const expected = { + battery_mV: 0, + charging: false, + dbm: -256, + swver: "0.0.15.24", + }; + + assert.deepEqual(expected, got); + }); });