Working tree changes 2024-08-08 01:00
All checks were successful
Test project build / Build (push) Successful in 1m12s
All checks were successful
Test project build / Build (push) Successful in 1m12s
This commit is contained in:
parent
4833283963
commit
356e0a9c56
1
.gitignore
vendored
1
.gitignore
vendored
@ -27,3 +27,4 @@
|
|||||||
!/niimbluelib/tsconfig.json
|
!/niimbluelib/tsconfig.json
|
||||||
!/niimbluelib/yarn.lock
|
!/niimbluelib/yarn.lock
|
||||||
!/niimbluelib/src
|
!/niimbluelib/src
|
||||||
|
!/niimbluelib/utils
|
||||||
|
@ -5,10 +5,14 @@ import {
|
|||||||
HeartbeatEvent,
|
HeartbeatEvent,
|
||||||
NiimbotBluetoothClient,
|
NiimbotBluetoothClient,
|
||||||
NiimbotSerialClient,
|
NiimbotSerialClient,
|
||||||
|
PacketReceivedEvent,
|
||||||
|
PacketSentEvent,
|
||||||
PrinterInfoFetchedEvent,
|
PrinterInfoFetchedEvent,
|
||||||
// PacketParsedEvent,
|
// PacketParsedEvent,
|
||||||
RawPacketReceivedEvent,
|
RawPacketReceivedEvent,
|
||||||
RawPacketSentEvent,
|
RawPacketSentEvent,
|
||||||
|
RequestCommandId,
|
||||||
|
ResponseCommandId,
|
||||||
Utils,
|
Utils,
|
||||||
type HeartbeatData,
|
type HeartbeatData,
|
||||||
type NiimbotAbstractClient,
|
type NiimbotAbstractClient,
|
||||||
@ -43,12 +47,21 @@ export const initClient = (connectionType: ConnectionType) => {
|
|||||||
newClient = new NiimbotSerialClient();
|
newClient = new NiimbotSerialClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
newClient.addEventListener("rawpacketsent", (e: RawPacketSentEvent) => {
|
// newClient.addEventListener("rawpacketsent", (e: RawPacketSentEvent) => {
|
||||||
console.log(`>> ${Utils.bufToHex(e.data)}`);
|
// console.log(`>> ${Utils.bufToHex(e.data)}`);
|
||||||
|
// });
|
||||||
|
|
||||||
|
newClient.addEventListener("packetsent", (e: PacketSentEvent) => {
|
||||||
|
console.log(`>> ${Utils.bufToHex(e.packet.toBytes())} (${RequestCommandId[e.packet.command]})`);
|
||||||
});
|
});
|
||||||
|
|
||||||
newClient.addEventListener("rawpacketreceived", (e: RawPacketReceivedEvent) => {
|
|
||||||
console.log(`<< ${Utils.bufToHex(e.data)}`);
|
// newClient.addEventListener("rawpacketreceived", (e: RawPacketReceivedEvent) => {
|
||||||
|
// console.log(`<< ${Utils.bufToHex(e.data)}`);
|
||||||
|
// });
|
||||||
|
|
||||||
|
newClient.addEventListener("packetreceived", (e: PacketReceivedEvent) => {
|
||||||
|
console.log(`<< ${Utils.bufToHex(e.packet.toBytes())} (${ResponseCommandId[e.packet.command]})`);
|
||||||
});
|
});
|
||||||
|
|
||||||
newClient.addEventListener("connect", (e: ConnectEvent) => {
|
newClient.addEventListener("connect", (e: ConnectEvent) => {
|
||||||
|
@ -33,6 +33,17 @@ export class PacketReceivedEvent extends Event {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export class PacketSentEvent extends Event {
|
||||||
|
packet: NiimbotPacket;
|
||||||
|
constructor(packet: NiimbotPacket) {
|
||||||
|
super("packetsent");
|
||||||
|
this.packet = packet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -83,6 +94,7 @@ export interface ClientEventMap {
|
|||||||
rawpacketsent: RawPacketSentEvent;
|
rawpacketsent: RawPacketSentEvent;
|
||||||
rawpacketreceived: RawPacketReceivedEvent;
|
rawpacketreceived: RawPacketReceivedEvent;
|
||||||
packetreceived: PacketReceivedEvent;
|
packetreceived: PacketReceivedEvent;
|
||||||
|
packetsent: PacketSentEvent;
|
||||||
heartbeat: HeartbeatEvent;
|
heartbeat: HeartbeatEvent;
|
||||||
printerinfofetched: PrinterInfoFetchedEvent;
|
printerinfofetched: PrinterInfoFetchedEvent;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
ProtocolVersion,
|
ProtocolVersion,
|
||||||
} from "../packets";
|
} from "../packets";
|
||||||
import { TypedEventTarget } from "typescript-event-target";
|
import { TypedEventTarget } from "typescript-event-target";
|
||||||
import { ClientEventMap, HeartbeatEvent, PrinterInfoFetchedEvent } from "./events";
|
import { ClientEventMap, HeartbeatEvent, PacketSentEvent, PrinterInfoFetchedEvent } from "./events";
|
||||||
import { Abstraction } from "../packets/abstraction";
|
import { Abstraction } from "../packets/abstraction";
|
||||||
import { getPrinterMetaById, PrinterModelMeta } from "..";
|
import { getPrinterMetaById, PrinterModelMeta } from "..";
|
||||||
|
|
||||||
@ -62,6 +62,7 @@ export abstract class NiimbotAbstractClient extends TypedEventTarget<ClientEvent
|
|||||||
|
|
||||||
public async sendPacket(packet: NiimbotPacket, force?: boolean) {
|
public async sendPacket(packet: NiimbotPacket, force?: boolean) {
|
||||||
await this.sendRaw(packet.toBytes(), force);
|
await this.sendRaw(packet.toBytes(), force);
|
||||||
|
this.dispatchTypedEvent("packetsent", new PacketSentEvent(packet));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Send "connect" packet and fetch the protocol version */
|
/** Send "connect" packet and fetch the protocol version */
|
||||||
|
@ -73,7 +73,7 @@ export class NiimbotSerialClient extends NiimbotAbstractClient {
|
|||||||
try {
|
try {
|
||||||
const result = await this.reader!.read();
|
const result = await this.reader!.read();
|
||||||
if (result.value) {
|
if (result.value) {
|
||||||
console.info(`<< serial chunk ${Utils.bufToHex(result.value)}`); // todo: remove
|
// console.info(`<< serial chunk ${Utils.bufToHex(result.value)}`);
|
||||||
|
|
||||||
const newBuf = new Uint8Array(buf.length + result.value.length);
|
const newBuf = new Uint8Array(buf.length + result.value.length);
|
||||||
newBuf.set(buf, 0);
|
newBuf.set(buf, 0);
|
||||||
|
85
niimbluelib/utils/gen-printer-models.js
Normal file
85
niimbluelib/utils/gen-printer-models.js
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// https://print.niimbot.com/api/hardware/list
|
||||||
|
|
||||||
|
fetch("https://oss-print.niimbot.com/public_resources/static_resources/devices.json")
|
||||||
|
.then((resp) => resp.json())
|
||||||
|
.then((items) => {
|
||||||
|
const dir_d = {
|
||||||
|
270: "left",
|
||||||
|
180: "top",
|
||||||
|
90: "left",
|
||||||
|
0: "top",
|
||||||
|
};
|
||||||
|
|
||||||
|
const ppmm_d = {
|
||||||
|
203: 8,
|
||||||
|
300: 11.81,
|
||||||
|
};
|
||||||
|
|
||||||
|
const labeltypes_d = {
|
||||||
|
"1": "LT.WithGaps",
|
||||||
|
"2": "LT.Black",
|
||||||
|
"3": "LT.Continuous",
|
||||||
|
"4": "LT.Perforated",
|
||||||
|
"5": "LT.Transparent",
|
||||||
|
"6": "LT.PvcTag",
|
||||||
|
"10": "LT.BlackMarkGap",
|
||||||
|
"11": "LT.HeatShrinkTube",
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("/* AUTO-GENERATED FILE. DO NOT EDIT! */");
|
||||||
|
console.log("/* use 'yarn gen-printer-models' to generate */\n");
|
||||||
|
console.log('import { PrintDirection, LabelType as LT } from ".";\n');
|
||||||
|
|
||||||
|
console.log("export enum PrinterModel {");
|
||||||
|
console.log(' UNKNOWN = "UNKNOWN",');
|
||||||
|
for (const item of items) {
|
||||||
|
const name = item.name.toUpperCase().replaceAll("-", "_");
|
||||||
|
console.log(` ${name} = "${name}",`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("};");
|
||||||
|
|
||||||
|
console.log(`
|
||||||
|
export interface PrinterModelMeta {
|
||||||
|
model: PrinterModel;
|
||||||
|
id: [number, ...number[]];
|
||||||
|
dpi: number;
|
||||||
|
printDirection: PrintDirection;
|
||||||
|
printheadPixels: number;
|
||||||
|
paperTypes: number[];
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
console.log("export const modelsLibrary: PrinterModelMeta[] = [");
|
||||||
|
for (const item of items) {
|
||||||
|
if (item.codes.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = item.name.toUpperCase().replaceAll("-", "_");
|
||||||
|
const dir = dir_d[item.printDirection];
|
||||||
|
const ppmm = ppmm_d[item.paccuracyName];
|
||||||
|
const paperTypes = item.paperType.split(',').map(e => labeltypes_d[e]).join(", ");
|
||||||
|
|
||||||
|
console.log(" {");
|
||||||
|
console.log(` model: PrinterModel.${name},`);
|
||||||
|
console.log(` id: [${item.codes.join(', ')}],`);
|
||||||
|
console.log(` dpi: ${item.paccuracyName},`);
|
||||||
|
console.log(` printDirection: "${dir}",`);
|
||||||
|
console.log(` printheadPixels: ${Math.ceil(item.widthSetEnd * ppmm)},`);
|
||||||
|
console.log(` paperTypes: [${paperTypes}],`);
|
||||||
|
console.log(" },");
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("];");
|
||||||
|
|
||||||
|
console.log(`
|
||||||
|
export const getPrinterMetaById = (id: number): PrinterModelMeta | undefined => {
|
||||||
|
return modelsLibrary.find((o) => o.id.includes(id));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getPrinterMetaByModel = (model: PrinterModel): PrinterModelMeta | undefined => {
|
||||||
|
return modelsLibrary.find((o) => o.model === model);
|
||||||
|
};`);
|
||||||
|
|
||||||
|
});
|
102
niimbluelib/utils/parse-dump.mjs
Normal file
102
niimbluelib/utils/parse-dump.mjs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import { Utils, NiimbotPacket, RequestCommandId, ResponseCommandId } from "../dist/index.js";
|
||||||
|
import { spawn } from "child_process";
|
||||||
|
|
||||||
|
const TSHARK_PATH = "C:\\Program Files\\Wireshark\\tshark.exe";
|
||||||
|
|
||||||
|
if (process.argv.length < 4 || !["usb", "ble"].includes(process.argv[2])) {
|
||||||
|
console.error("usage: yarn parse-dump <ble|usb> <filename> [min|min-out]");
|
||||||
|
}
|
||||||
|
|
||||||
|
const capType = process.argv[2];
|
||||||
|
const capPath = process.argv[3];
|
||||||
|
const args = ["-2", "-r", capPath, "-P", "-T", "fields", "-e", /*"frame.time_relative"*/ "frame.time_delta"];
|
||||||
|
const display = process.argv.length > 4 ? process.argv[4] : "";
|
||||||
|
|
||||||
|
if (capType === "ble") {
|
||||||
|
args.push("-R", "btspp.data", "-e", "hci_h4.direction", "-e", "btspp.data");
|
||||||
|
} else {
|
||||||
|
args.push("-R", "usb.capdata", "-e", "usb.dst", "-e", "usb.capdata");
|
||||||
|
}
|
||||||
|
|
||||||
|
const spawned = spawn(TSHARK_PATH, args);
|
||||||
|
|
||||||
|
let output = "";
|
||||||
|
|
||||||
|
spawned.stdout.on("data", (data) => {
|
||||||
|
output += data.toString();
|
||||||
|
});
|
||||||
|
|
||||||
|
spawned.stderr.on("data", (data) => {
|
||||||
|
console.error(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
spawned.on("close", (code) => {
|
||||||
|
console.log(`child process exited with code ${code}`);
|
||||||
|
|
||||||
|
if (code !== 0) {
|
||||||
|
console.error(output);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lines = output.split(/\r?\n/);
|
||||||
|
let printStarted = false;
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
const splitted = line.split("\t");
|
||||||
|
|
||||||
|
if (splitted.length !== 3) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let [time, direction, hexData] = splitted;
|
||||||
|
direction = ["host", "0x01"].includes(direction) ? "<<" : ">>";
|
||||||
|
|
||||||
|
let comment = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = Utils.hexToBuf(hexData);
|
||||||
|
const packets = NiimbotPacket.fromBytesMultiPacket(data);
|
||||||
|
|
||||||
|
if (packets.length === 0) {
|
||||||
|
comment = "Parse error (no packets found)";
|
||||||
|
} else if (packets.length > 1) {
|
||||||
|
comment = `Multi-packet (x${packets.length}); `;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const packet of packets) {
|
||||||
|
if (direction === ">>") {
|
||||||
|
comment += RequestCommandId[packet.command] ?? "???";
|
||||||
|
if (packet.command === RequestCommandId.PrintStart) {
|
||||||
|
printStarted = true;
|
||||||
|
const versions = { 1: "v1", 2: "v3", 7: "v4", 8: "v5" };
|
||||||
|
comment += "_" + versions[packet.dataLength];
|
||||||
|
} else if (packet.command === RequestCommandId.SetPageSize) {
|
||||||
|
const versions = { 2: "v1", 4: "v2", 6: "v3", 8: "v5" };
|
||||||
|
comment += "_" + versions[packet.dataLength];
|
||||||
|
}else if (packet.command === RequestCommandId.PrintEnd) {
|
||||||
|
printStarted = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
comment += ResponseCommandId[packet.command] ?? "???";
|
||||||
|
}
|
||||||
|
comment += `(${packet.dataLength}); `;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
comment = "Invalid packet";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (display === "min") {
|
||||||
|
console.log(`${direction} ${comment}`);
|
||||||
|
} else if (display === "min-out") {
|
||||||
|
if (direction === ">>") {
|
||||||
|
console.log(`${direction} ${comment}`);
|
||||||
|
}
|
||||||
|
} else if (display === "print-task") {
|
||||||
|
if (direction === ">>" && printStarted) {
|
||||||
|
console.log(`${direction} ${comment}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(`[${time}] ${direction} ${hexData}\t// ${comment}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
0
niimbluelib/utils/test.mjs
Normal file
0
niimbluelib/utils/test.mjs
Normal file
Reference in New Issue
Block a user