From b023425365b4508cf0b85287046bf34cc44c1eba Mon Sep 17 00:00:00 2001 From: MultiMote Date: Thu, 9 Jan 2025 22:08:54 +0300 Subject: [PATCH] Add firmware update functionality, fix packet parser bugs * Support for CRC32 packets * Packet parser rewrite (packet was not parsed when extra 0xaa or 0x55 byte is met) --- docs/documents/niimbot_proto.md | 93 +++-- docs/documents/proto/crc32packet.png | Bin 0 -> 127563 bytes docs/documents/proto/crc32packet.svg | 503 +++++++++++++++++++++++++++ package.json | 1 + src/client/abstract_client.ts | 15 +- src/events.ts | 18 +- src/packets/abstraction.ts | 59 +++- src/packets/commands.ts | 20 ++ src/packets/index.ts | 1 + src/packets/packet.ts | 174 ++++++--- src/packets/packet_generator.ts | 35 ++ src/packets/packet_parser.ts | 88 +++++ src/utils.ts | 32 +- yarn.lock | 5 + 14 files changed, 955 insertions(+), 89 deletions(-) create mode 100644 docs/documents/proto/crc32packet.png create mode 100644 docs/documents/proto/crc32packet.svg create mode 100644 src/packets/packet_parser.ts diff --git a/docs/documents/niimbot_proto.md b/docs/documents/niimbot_proto.md index 81365ab..a6b1842 100644 --- a/docs/documents/niimbot_proto.md +++ b/docs/documents/niimbot_proto.md @@ -8,6 +8,8 @@ WIP ## Packet structure +### Main packet + ![](proto/packet.png) * **Prefix** - prefix `0x03` is present in only one command - **Connect**. @@ -18,41 +20,68 @@ WIP * **Checksum** - calculated by XOR of all bytes from **Command** to the last byte of **Data** (inclusive). * **Tail** - always 2 bytes (`0xAA` `0xAA`). +### CRC32 (firmware) packet + +![](proto/crc32packet.png) + +* **Head** - always 2 bytes (`0x55` `0x55`). +* **Command** - command (packet) identifier. +* **Index** - firmware chunk index, used only in `FirmwareChunk` and `In_RequestFirmwareChunk` packets, otherwise equals zero. +* **Data Length** - number of bytes of data. +* **Data** - data with **Data length** length. +* **Checksum** - crc32 checksum of all bytes from **Command** to the last byte of **Data** (inclusive). +* **Tail** - always 2 bytes (`0xAA` `0xAA`). + ## List of packets -| Request ID | Name | Response ID(s) | [Simple](#simple-packet) | +| Request ID | Name | Response ID(s) | [Simple](#simple-packet) | CRC32 | +|------|------------|------|-|-| +| 0x01 | PrintStart | 0x02 |✅| | +| 0x03 | PageStart | 0x04 |✅| | +| 0x05 | PrinterLog | 0x06 |✅| | +| 0x0b | AntiFake | 0x0c |✅| | +| 0x13 | SetPageSize | 0x14 | | | +| 0x15 | PrintQuantity | 0x16 | | | +| 0x1a | RfidInfo | 0x1b |✅| | +| 0x1c | RfidInfo2 | 0x1d |✅| | +| 0x20 | PrintClear | 0x30 |✅| | +| 0x21 | SetDensity | 0x31 | | | +| 0x23 | SetLabelType | 0x33 | | | +| 0x27 | SetAutoShutdownTime | 0x37 | | | +| 0x28 | PrinterReset | 0x38 |✅| | +| 0x40 | PrinterInfo | 0x4f, 0x47, 0x4d, 0x4a, 0x41, 0x4c, 0x43, 0x46, 0x48, 0x4b, 0x49, 0x42 | | | +| 0x54 | RfidSuccessTimes | 0x64 |✅| | +| 0x58 | SoundSettings | 0x68 | | | +| 0x59 | CalibrateHeight | 0x69 | | | +| 0x5a | PrintTestPage | 0x6a |✅| | +| 0x70 | WriteRFID | 0x71 | | | +| 0x83 | [PrintBitmapRowIndexed](#printbitmaprowindexed) | ⚠ one way | | | +| 0x84 | [PrintEmptyRow](#printemptyrow) | ⚠ one way | | | +| 0x85 | [PrintBitmapRow](#printbitmaprow) | ⚠ one way | | | +| 0x8e | LabelPositioningCalibration | 0x8f |✅| | +| 0x91 | FirmwareCrc | ⚠ one way | |✅| +| 0x92 | FirmwareCommit | ⚠ one way | |✅| +| 0x9b | FirmwareChunk | ⚠ one way | |✅| +| 0x9c | FirmwareNoMoreChunks | ⚠ one way | |✅| +| 0xa3 | PrintStatus | 0xb3 |✅| | +| 0xa5 | PrinterStatusData | 0xb5 |✅| | +| 0xaf | PrinterConfig | 0xbf | | | +| 0xc1 | Connect | 0xc2 |✅| | +| 0xda | CancelPrint | 0xd0 |✅| | +| 0xdc | Heartbeat | 0xde, 0xdf, 0xdd, 0xd9 | | | +| 0xe3 | PageEnd | 0xe4 |✅| | +| 0xf3 | PrintEnd | 0xf4 |✅| | +| 0xf5 | StartFirmwareUpgrade | 0xf6 | | | + +Comes from printer only: + +| Request ID | Name | Client response ID | CRC32 | |------|------------|------|-| -| 0x01 | PrintStart | 0x02 |✅| -| 0x03 | PageStart | 0x04 |✅| -| 0x05 | PrinterLog | 0x06 |✅| -| 0x0b | AntiFake | 0x0c |✅| -| 0x13 | SetPageSize | 0x14 | | -| 0x15 | PrintQuantity | 0x16 | | -| 0x1a | RfidInfo | 0x1b |✅| -| 0x1c | RfidInfo2 | 0x1d |✅| -| 0x20 | PrintClear | 0x30 |✅| -| 0x21 | SetDensity | 0x31 | | -| 0x23 | SetLabelType | 0x33 | | -| 0x27 | SetAutoShutdownTime | 0x37 | | -| 0x28 | PrinterReset | 0x38 |✅| -| 0x40 | PrinterInfo | 0x4f, 0x47, 0x4d, 0x4a, 0x41, 0x4c, 0x43, 0x46, 0x48, 0x4b, 0x49, 0x42 | | -| 0x54 | RfidSuccessTimes | 0x64 |✅| -| 0x58 | SoundSettings | 0x68 | | -| 0x59 | CalibrateHeight | 0x69 | | -| 0x5a | PrintTestPage | 0x6a |✅| -| 0x70 | WriteRFID | 0x71 | | -| 0x83 | [PrintBitmapRowIndexed](#printbitmaprowindexed) | ⚠ one way | | -| 0x84 | [PrintEmptyRow](#printemptyrow) | ⚠ one way | | -| 0x85 | [PrintBitmapRow](#printbitmaprow) | ⚠ one way | | -| 0x8e | LabelPositioningCalibration | 0x8f |✅| -| 0xa3 | PrintStatus | 0xb3 |✅| -| 0xa5 | PrinterStatusData | 0xb5 |✅| -| 0xaf | PrinterConfig | 0xbf | | -| 0xc1 | Connect | 0xc2 |✅| -| 0xda | CancelPrint | 0xd0 |✅| -| 0xdc | Heartbeat | 0xde, 0xdf, 0xdd, 0xd9 | | -| 0xe3 | PageEnd | 0xe4 |✅| -| 0xf3 | PrintEnd | 0xf4 |✅| +| 0xe0 | In_PrinterPageIndex | | +| 0x90 | In_RequestFirmwareCrc | 0x91 |✅| +| 0x9a | In_RequestFirmwareChunk | 0x9b |✅| +| 0x9d | In_FirmwareCheckResult | |✅| +| 0x9e | In_FirmwareResult | |✅| ## Packet details diff --git a/docs/documents/proto/crc32packet.png b/docs/documents/proto/crc32packet.png new file mode 100644 index 0000000000000000000000000000000000000000..30a56552e538271402de4cc7b2cab6170b22666f GIT binary patch literal 127563 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 literal 0 HcmV?d00001 diff --git a/docs/documents/proto/crc32packet.svg b/docs/documents/proto/crc32packet.svg new file mode 100644 index 0000000..571cc55 --- /dev/null +++ b/docs/documents/proto/crc32packet.svg @@ -0,0 +1,503 @@ + + + + + + + + + + + + + + + + + + + 55 + 55 + AA + AA + + + + + + 02 + 01 + .. + 10 + DD + + AA + 01 + + 00 + Head + Command + Tail + Data + Data length + + + + + + 00 + + + + + Checksum + + + Index + + + + + BB + + CC + + + + + + + MultiMote + + + + + + diff --git a/package.json b/package.json index 481b55e..397a529 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "@capacitor-community/bluetooth-le": "^6.0.2", "@capacitor/core": "^6.0.0", "async-mutex": "^0.5.0", + "crc-32": "^1.2.2", "eventemitter3": "^5.0.1" }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" diff --git a/src/client/abstract_client.ts b/src/client/abstract_client.ts index 7f9409a..2184952 100644 --- a/src/client/abstract_client.ts +++ b/src/client/abstract_client.ts @@ -7,6 +7,7 @@ import { ConnectResult, LabelType, NiimbotPacket, + PacketParser, PrinterErrorCode, PrintError, ResponseCommandId, @@ -75,7 +76,10 @@ export abstract class NiimbotAbstractClient extends EventEmitter super(); this.abstraction = new Abstraction(this); this.on("connect", () => this.startHeartbeat()); - this.on("disconnect", () => this.stopHeartbeat()); + this.on("disconnect", () => { + this.stopHeartbeat(); + this.packetBuf = new Uint8Array(); + }); } /** @@ -179,8 +183,13 @@ export abstract class NiimbotAbstractClient extends EventEmitter this.packetBuf = Utils.u8ArrayAppend(this.packetBuf, data); + if (this.packetBuf.length > 1 && !Utils.hasSubarrayAtPos(this.packetBuf, NiimbotPacket.HEAD, 0)) { + console.warn("Dropping invalid buffer", Utils.bufToHex(this.packetBuf)); + this.packetBuf = new Uint8Array(); + } + try { - const packets: NiimbotPacket[] = NiimbotPacket.fromBytesMultiPacket(this.packetBuf); + const packets: NiimbotPacket[] = PacketParser.parsePacketBundle(this.packetBuf); if (packets.length > 0) { this.emit("rawpacketreceived", new RawPacketReceivedEvent(this.packetBuf)); @@ -193,7 +202,7 @@ export abstract class NiimbotAbstractClient extends EventEmitter } } catch (_e) { if (this.debug) { - console.info(`Incomplete packet, ignoring:${Utils.bufToHex(this.packetBuf)}`); + console.info(`Incomplete packet, ignoring:${Utils.bufToHex(this.packetBuf)}`, _e); } } } diff --git a/src/events.ts b/src/events.ts index 758bb18..0a27424 100644 --- a/src/events.ts +++ b/src/events.ts @@ -119,7 +119,7 @@ export class PrinterInfoFetchedEvent extends NiimbotEvent { } /** - * Fired progress received (during {@link AbstractPrintTask.waitForFinished}). + * Fired on print progress received during {@link AbstractPrintTask.waitForFinished}. * @category Events */ export class PrintProgressEvent extends NiimbotEvent { @@ -141,6 +141,21 @@ export class PrintProgressEvent extends NiimbotEvent { } } +/** + * Fired on firmware upload progress during {@link Abstraction.firmwareUpgrade}. + * @category Events + */ +export class FirmwareProgressEvent extends NiimbotEvent { + currentChunk: number; + totalChunks: number; + + constructor(currentChunk: number, totalChunks: number) { + super("firmwareprogress"); + this.currentChunk = currentChunk; + this.totalChunks = totalChunks; + } +} + /** * Event list for {@link NiimbotAbstractClient}. * @category Events @@ -156,4 +171,5 @@ export type ClientEventMap = { heartbeatfailed: (event: HeartbeatFailedEvent) => void; printerinfofetched: (event: PrinterInfoFetchedEvent) => void; printprogress: (event: PrintProgressEvent) => void; + firmwareprogress: (event: FirmwareProgressEvent) => void; }; diff --git a/src/packets/abstraction.ts b/src/packets/abstraction.ts index e30638b..094827b 100644 --- a/src/packets/abstraction.ts +++ b/src/packets/abstraction.ts @@ -10,13 +10,14 @@ import { SoundSettingsType, } from "."; import { NiimbotAbstractClient } from "../client"; -import { PacketReceivedEvent, PrintProgressEvent } from "../events"; +import { FirmwareProgressEvent, PacketReceivedEvent, PrintProgressEvent } from "../events"; import { PrintTaskName, printTasks } from "../print_tasks"; import { AbstractPrintTask, PrintOptions } from "../print_tasks/AbstractPrintTask"; import { Validators, Utils } from "../utils"; import { SequentialDataReader } from "./data_reader"; -import { NiimbotPacket } from "./packet"; +import { NiimbotCrc32Packet, NiimbotPacket } from "./packet"; import { PacketGenerator } from "./packet_generator"; +import CRC32 from "crc-32"; /** * @category Packets @@ -453,7 +454,7 @@ export class Abstraction { this.statusPollTimer = setInterval(() => { this.printEnd() .then((printEndDone: boolean) => { - if(!printEndDone) { + if (!printEndDone) { this.client.emit("printprogress", new PrintProgressEvent(1, pagesToPrint, 0, 0)); } else { this.client.emit("printprogress", new PrintProgressEvent(pagesToPrint, pagesToPrint, 100, 100)); @@ -486,6 +487,58 @@ export class Abstraction { return response.data[0] === 1; } + public async firmwareUpgrade(data: Uint8Array, version: string): Promise { + const crc = CRC32.buf(data); + await this.send(PacketGenerator.startFirmwareUpgrade(version)); + + await this.client.waitForPacket([ResponseCommandId.In_RequestFirmwareCrc], true, 5_000); + + await this.send(PacketGenerator.sendFirmwareChecksum(crc)); + + const chunkSize = 200; + const totalChunks = Math.floor(data.byteLength / chunkSize); + console.log("Chunks to send:", totalChunks); + + // Send chunks + while (true) { + const p = await this.client.waitForPacket([ResponseCommandId.In_RequestFirmwareChunk], true, 5_000); + + if (!(p instanceof NiimbotCrc32Packet)) { + throw new Error("Not a firmware packet"); + } + + if (p.chunkNumber * chunkSize >= data.length) { + console.log("No more chunks"); + break; + } + + const part = data.slice(p.chunkNumber * chunkSize, p.chunkNumber * chunkSize + chunkSize); + + await this.send(PacketGenerator.sendFirmwareChunk(p.chunkNumber, part)); + + this.client.emit("firmwareprogress", new FirmwareProgressEvent(p.chunkNumber, totalChunks)); + } + + await this.send(PacketGenerator.firmwareNoMoreChunks()); + + const uploadResult = await this.client.waitForPacket([ResponseCommandId.In_FirmwareCheckResult], true, 5_000); + Validators.u8ArrayLengthEquals(uploadResult.data, 1); + + if (uploadResult.data[0] !== 1) { + throw new Error("Firmware check error (maybe CRC does not match)"); + } + + await this.send(PacketGenerator.firmwareCommit()); + + const firmwareResult = await this.client.waitForPacket([ResponseCommandId.In_FirmwareResult], true, 5_000); + + Validators.u8ArrayLengthEquals(firmwareResult.data, 1); + + if (firmwareResult.data[0] !== 1) { + throw new Error("Firmware error"); + } + } + public newPrintTask(name: PrintTaskName, options?: Partial): AbstractPrintTask { return new printTasks[name](this, options); } diff --git a/src/packets/commands.ts b/src/packets/commands.ts index ba9628f..0f78ce3 100644 --- a/src/packets/commands.ts +++ b/src/packets/commands.ts @@ -41,6 +41,11 @@ export enum RequestCommandId { /** same as GetVolumeLevel??? */ WriteRFID = 0x70, PrintTestPage = 0x5a, + StartFirmwareUpgrade = 0xf5, + FirmwareCrc = 0x91, + FirmwareCommit = 0x92, + FirmwareChunk = 0x9b, + FirmwareNoMoreChunks = 0x9c, } /** @@ -98,6 +103,11 @@ export enum ResponseCommandId { In_PrinterPageIndex = 0xe0, In_PrintTestPage = 0x6a, In_WriteRFID = 0x71, + In_StartFirmwareUpgrade = 0xf6, + In_RequestFirmwareCrc = 0x90, + In_RequestFirmwareChunk = 0x9a, + In_FirmwareCheckResult = 0x9d, + In_FirmwareResult = 0x9e, } import TX = RequestCommandId; @@ -154,4 +164,14 @@ export const commandsMap: Record = [TX.AntiFake]: [RX.In_AntiFake], [TX.WriteRFID]: [RX.In_WriteRFID], [TX.PrintTestPage]: [RX.In_PrintTestPage], + [TX.StartFirmwareUpgrade]: [RX.In_StartFirmwareUpgrade], + [TX.FirmwareCrc]: null, + [TX.FirmwareChunk]: null, + [TX.FirmwareNoMoreChunks]: null, + [TX.FirmwareCommit]: null, +}; + +export const firmwareExchangePackets: { tx: RequestCommandId[]; rx: ResponseCommandId[] } = { + tx: [TX.FirmwareChunk, TX.FirmwareCrc, TX.FirmwareNoMoreChunks, TX.FirmwareCommit], + rx: [RX.In_RequestFirmwareCrc, RX.In_RequestFirmwareChunk, RX.In_FirmwareCheckResult, RX.In_FirmwareResult], }; diff --git a/src/packets/index.ts b/src/packets/index.ts index b3b8a0e..6fe414f 100644 --- a/src/packets/index.ts +++ b/src/packets/index.ts @@ -2,5 +2,6 @@ export * from "./packet"; export * from "./commands"; export * from "./payloads"; export * from "./packet_generator"; +export * from "./packet_parser"; export * from "./abstraction"; export * from "./data_reader"; diff --git a/src/packets/packet.ts b/src/packets/packet.ts index b8daf50..73fc80f 100644 --- a/src/packets/packet.ts +++ b/src/packets/packet.ts @@ -1,17 +1,19 @@ -import { Validators } from "../utils"; -import { RequestCommandId, ResponseCommandId } from "."; +import { Utils, Validators } from "../utils"; +import { firmwareExchangePackets, RequestCommandId, ResponseCommandId } from "."; +import CRC32 from "crc-32"; /** * NIIMBOT packet object - * + * * @category Packets */ export class NiimbotPacket { public static readonly HEAD = new Uint8Array([0x55, 0x55]); public static readonly TAIL = new Uint8Array([0xaa, 0xaa]); - private _command: RequestCommandId | ResponseCommandId; - private _data: Uint8Array; + protected _command: RequestCommandId | ResponseCommandId; + protected _data: Uint8Array; + private _validResponseIds: ResponseCommandId[]; /** There can be no response after this request. */ @@ -71,7 +73,7 @@ export class NiimbotPacket { return checksum; } - // [0x55, 0x55, CMD, DATA_LEN, DA =//= TA, CHECKSUM, 0xAA, 0xAA] + /** [0x55, 0x55, CMD, DATA_LEN, DA =//= TA, CHECKSUM, 0xAA, 0xAA] */ public toBytes(): Uint8Array { const buf = new ArrayBuffer( NiimbotPacket.HEAD.length + // head @@ -138,62 +140,136 @@ export class NiimbotPacket { throw new Error(`Invalid packet size (${buf.length} < ${minPacketSize + dataLen})`); } - const data: Uint8Array = new Uint8Array(buf.slice(4, 4 + dataLen)); + const data: Uint8Array = buf.slice(4, 4 + dataLen); const checksum: number = buf[4 + dataLen]; const packet = new NiimbotPacket(cmd, data); if (packet.checksum !== checksum) { - throw new Error("Invalid packet checksum"); + throw new Error(`Invalid packet checksum (${packet.checksum} !== ${checksum})`); } return packet; } +} + +/** + * NIIMBOT packet object with CRC32 checksum. Used in firmware process. + * + * @category Packets + */ +export class NiimbotCrc32Packet extends NiimbotPacket { + private _chunkNumber: number; - /** Parse data containing one or more packets */ - public static fromBytesMultiPacket(buf: Uint8Array): NiimbotPacket[] { - const chunks: Uint8Array[] = []; - - let head1pos = -1; - let head2pos = -1; - let tail1pos = -1; - let tail2pos = -1; - - // split data to chunks by head and tail bytes - for (let i = 0; i < buf.length; i++) { - const v = buf[i]; - if (v === NiimbotPacket.HEAD[0]) { - if (head1pos === -1) { - head1pos = i; - head2pos = -1; - } else { - head2pos = i; - } - } else if (v === NiimbotPacket.TAIL[0]) { - if (head1pos !== -1 && head2pos !== -1) { - if (tail1pos === -1) { - tail1pos = i; - tail2pos = -1; - } else { - tail2pos = i; - } - } - } - - if (head1pos !== -1 && head2pos !== -1 && tail1pos !== -1 && tail2pos !== -1) { - chunks.push(buf.slice(head1pos, tail2pos + 1)); - head1pos = -1; - head2pos = -1; - tail1pos = -1; - tail2pos = -1; - } + constructor( + command: RequestCommandId | ResponseCommandId, + chunkNumber: RequestCommandId | ResponseCommandId, + data: Uint8Array | number[], + validResponseIds: ResponseCommandId[] = [] + ) { + super(command, data, validResponseIds); + this._chunkNumber = chunkNumber; + } + + public get chunkNumber(): number { + return this._chunkNumber; + } + + /** Calculate CRC checksum from command and data */ + public override get checksum(): number { + const data = [this._command, ...Utils.u16ToBytes(this._chunkNumber), this._data.length, ...this._data]; + return CRC32.buf(data); + } + + public static override fromBytes(buf: Uint8Array): NiimbotCrc32Packet { + //throw new Error("Not implemented"); + + const head = new Uint8Array(buf.slice(0, 2)); + const tail = new Uint8Array(buf.slice(buf.length - 2)); + const minPacketSize = + NiimbotPacket.HEAD.length + // head + 1 + // cmd + 2 + // chunkNumber + 1 + // dataLength + 4 + // checksum + NiimbotPacket.TAIL.length; + + if (buf.length < minPacketSize) { + throw new Error(`Packet is too small (${buf.length} < ${minPacketSize})`); } - const chunksDataLen: number = chunks.reduce((acc: number, b: Uint8Array) => acc + b.length, 0); + Validators.u8ArraysEqual(head, NiimbotPacket.HEAD, "Invalid packet head"); + + Validators.u8ArraysEqual(tail, NiimbotPacket.TAIL, "Invalid packet tail"); + + const cmd: number = buf[2]; + + const chunkNumber: number = Utils.bytesToI16(buf.slice(3, 5)); - if (buf.length !== chunksDataLen) { - throw new Error("Splitted chunks data length not equals buffer length"); + const dataLen: number = buf[5]; + + if (buf.length !== minPacketSize + dataLen) { + throw new Error(`Invalid packet size (${buf.length} < ${minPacketSize + dataLen})`); } - return chunks.map((c) => this.fromBytes(c)); + const data: Uint8Array = buf.slice(6, 6 + dataLen); + + const checksum: number = Utils.bytesToI32(buf.slice(6 + dataLen, 6 + dataLen + 4)); + + const packet = new NiimbotCrc32Packet(cmd, chunkNumber, data); + + if (packet.checksum !== checksum) { + throw new Error(`Invalid packet checksum (${packet.checksum} !== ${checksum})`); + } + + return packet; + } + + /** [0x55, 0x55, CMD, CHUNK_NUMBER, DATA_SIZE, DA =//= TA, CRC32_CHECKSUM, 0xAA, 0xAA] */ + public override toBytes(): Uint8Array { + const buf = new ArrayBuffer( + NiimbotPacket.HEAD.length + // head + 1 + // cmd + 2 + // chunkNumber + 1 + // dataLength + this._data.length + + 4 + // checksum + NiimbotPacket.TAIL.length + ); + + const arr = new Uint8Array(buf); + + let pos = 0; + + arr.set(NiimbotPacket.HEAD, pos); + pos += NiimbotPacket.HEAD.length; + + arr[pos] = this._command; + pos += 1; + + const [h, l] = Utils.u16ToBytes(this._chunkNumber); + arr[pos] = h; + pos += 1; + arr[pos] = l; + pos += 1; + + arr[pos] = this._data.length; + pos += 1; + + arr.set(this._data, pos); + pos += this._data.length; + + const crc = this.checksum; + arr[pos] = (crc >> 24) & 0xff; + pos += 1; + arr[pos] = (crc >> 16) & 0xff; + pos += 1; + arr[pos] = (crc >> 8) & 0xff; + pos += 1; + arr[pos] = crc & 0xff; + pos += 1; + + arr.set(NiimbotPacket.TAIL, pos); + + return arr; } } diff --git a/src/packets/packet_generator.ts b/src/packets/packet_generator.ts index e1b6a3c..42aea3b 100644 --- a/src/packets/packet_generator.ts +++ b/src/packets/packet_generator.ts @@ -8,6 +8,7 @@ import { SoundSettingsItemType, SoundSettingsType, commandsMap, + NiimbotCrc32Packet, } from "."; import { EncodedImage, ImageEncoder, ImageRow } from "../image_encoder"; import { Utils } from "../utils"; @@ -245,4 +246,38 @@ export class PacketGenerator { public static labelPositioningCalibration(value: number): NiimbotPacket { return this.mapped(TX.LabelPositioningCalibration, [value]); } + + public static startFirmwareUpgrade(version: string): NiimbotPacket { + if(!/^\d+\.\d+$/.test(version)) { + throw new Error("Invalid version format (x.x expected)"); + } + + const [a, b] = version.split(".").map(p => parseInt(p)); + + return this.mapped(TX.StartFirmwareUpgrade, [a, b]); + } + + public static sendFirmwareChecksum(crc: number): NiimbotPacket { + const p = new NiimbotCrc32Packet(TX.FirmwareCrc, 0, [...Utils.u32ToBytes(crc)]); + p.oneWay = true; + return p; + } + + public static sendFirmwareChunk(idx: number, data: Uint8Array): NiimbotPacket { + const p = new NiimbotCrc32Packet(TX.FirmwareChunk, idx, data); + p.oneWay = true; + return p; + } + + public static firmwareNoMoreChunks(): NiimbotPacket { + const p = new NiimbotCrc32Packet(TX.FirmwareNoMoreChunks, 0, [1]); + p.oneWay = true; + return p; + } + + public static firmwareCommit(): NiimbotPacket { + const p = new NiimbotCrc32Packet(TX.FirmwareCommit, 0, [1]); + p.oneWay = true; + return p; + } } diff --git a/src/packets/packet_parser.ts b/src/packets/packet_parser.ts new file mode 100644 index 0000000..8efc852 --- /dev/null +++ b/src/packets/packet_parser.ts @@ -0,0 +1,88 @@ +import { firmwareExchangePackets, NiimbotCrc32Packet, NiimbotPacket } from "."; +import { Utils } from "../utils"; + +/** + * Packet parsers. + * + * @category Packets + **/ +export class PacketParser { + /** + * Parse raw data containing one or more packets. + * + * For example, `55554a01044faaaa5555f60101f6aaaa` will be converted to the two NiimbotPackets. + * + * @param buf bytes + * @returns list of packet objects + */ + public static parsePacketBundle(buf: Uint8Array): NiimbotPacket[] { + type PacketClass = typeof NiimbotPacket | typeof NiimbotCrc32Packet; + type ChunkType = { cls: typeof NiimbotPacket | typeof NiimbotCrc32Packet; raw: Uint8Array }; + const chunks: ChunkType[] = []; + const bufLength: number = buf.byteLength; + + while (buf.byteLength > 0) { + if (!Utils.hasSubarrayAtPos(buf, NiimbotPacket.HEAD, 0)) { + break; + } + + if (buf.byteLength < 3) { + break; + } + + const cmd: number = buf[2]; + let cls: PacketClass = NiimbotPacket; + + let sizePos: number = 3; + let crcSize: number = 1; + // 0 1 2 3 4 5 6 7 + // ----------------------- + // 55 55 4a 01 04 4f aa aa + // | | + // size crc + + if (firmwareExchangePackets.rx.includes(cmd)) { + cls = NiimbotCrc32Packet; + sizePos = 5; + crcSize = 4; + // 0 1 2 3 4 5 6 7 8 9 10 11 12 + // -------------------------------------- + // 55 55 9a 00 80 01 01 d2 bd d2 fb aa aa + // | |---------| + // size crc + } + + if (buf.byteLength <= sizePos) { + break; + } + + const size: number = buf[sizePos]; + + if (buf.byteLength <= sizePos + size + crcSize + NiimbotPacket.TAIL.byteLength) { + break; + } + + const tailPos: number = sizePos + size + crcSize + 1; + + if (!Utils.hasSubarrayAtPos(buf, NiimbotPacket.TAIL, tailPos)) { + console.warn("Invalid tail"); + break; + } + + let tailEnd: number = tailPos + NiimbotPacket.TAIL.byteLength; + + chunks.push({ cls, raw: buf.slice(0, tailEnd) }); + + // Cut form start + buf = buf.slice(tailEnd); + } + + const chunksDataLen: number = chunks.reduce((acc: number, c: ChunkType) => acc + c.raw.length, 0); + + if (bufLength !== chunksDataLen) { + throw new Error(`Splitted chunks data length not equals buffer length (${bufLength} !== ${chunksDataLen})`); + } + + return chunks.map((c) => c.cls.fromBytes(c.raw)); + } +} diff --git a/src/utils.ts b/src/utils.ts index 5945619..b78177b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -119,12 +119,27 @@ export class Utils { return [h, l]; } + /** + * Converts a 32-bit unsigned integer to an array of two bytes (big endian). + */ + public static u32ToBytes(n: number): [number, number, number, number] { + return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]; + } + /** * Converts a Uint8Array of length 2 to a 16-bit signed integer (big endian). */ public static bytesToI16(arr: Uint8Array): number { Validators.u8ArrayLengthEquals(arr, 2); - return arr[0] * 256 + arr[1]; + return new DataView(arr.buffer).getInt16(0, false); + } + + /** + * Converts a Uint8Array of length 2 to a 16-bit signed integer (big endian). + */ + public static bytesToI32(arr: Uint8Array): number { + Validators.u8ArrayLengthEquals(arr, 4); + return new DataView(arr.buffer).getInt32(0, false); } /** @@ -174,6 +189,21 @@ export class Utils { webSerial: typeof navigator.serial?.requestPort !== "undefined", }; } + + /** Find check array has subarray at index */ + public static hasSubarrayAtPos(arr: ArrayLike, sub: ArrayLike, pos: number): boolean { + if (pos > arr.length - sub.length) { + return false; + } + + for (let i = 0; i < sub.length; i++) { + if (arr[pos + i] !== sub[i]) { + return false; + } + } + + return true; + } } /** diff --git a/yarn.lock b/yarn.lock index 4589997..be97a17 100644 --- a/yarn.lock +++ b/yarn.lock @@ -40,6 +40,11 @@ async-mutex@^0.5.0: dependencies: tslib "^2.4.0" +crc-32@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + eventemitter3@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4"