This repository has been archived on 2024-09-16. You can view files and clone it, but cannot push or open issues or pull requests.

156 lines
4.3 KiB
TypeScript

import { ConnectionInfo, NiimbotAbstractClient } from ".";
import { ConnectResult, NiimbotPacket } from "../packets";
import { Utils } from "../utils";
import { ConnectEvent, DisconnectEvent, RawPacketSentEvent } from "./events";
/** WIP. Uses serial communication, Works worse than NiimbotBluetoothClient at the moment, events are not firing */
export class NiimbotSerialClient extends NiimbotAbstractClient {
private port?: SerialPort = undefined;
private writer?: WritableStreamDefaultWriter<Uint8Array> = undefined;
public async connect(): Promise<ConnectionInfo> {
this.disconnect();
const _port: SerialPort = await navigator.serial.requestPort();
_port.addEventListener("disconnect", () => {
this.port = undefined;
this.dispatchTypedEvent("disconnect", new DisconnectEvent());
});
await _port.open({ baudRate: 115200 });
if (_port.writable === null) {
throw new Error("Port is not writable");
}
this.port = _port;
this.writer = _port.writable.getWriter();
const info = _port.getInfo();
try {
await this.initialNegotiate();
await this.fetchPrinterInfo();
} catch (e) {
console.error(e);
}
const result: ConnectionInfo = {
deviceName: `Serial (VID:${info.usbVendorId?.toString(16)} PID:${info.usbProductId?.toString(16)})`,
result: this.info.connectResult ?? ConnectResult.FirmwareErrors
};
this.dispatchTypedEvent("connect", new ConnectEvent(result));
return result;
}
public async disconnect() {
if (this.writer !== undefined) {
this.writer.releaseLock();
}
if (this.port !== undefined) {
this.port.close();
this.dispatchTypedEvent("disconnect", new DisconnectEvent());
}
this.port = undefined;
this.writer = undefined;
}
public isConnected(): boolean {
throw this.port !== undefined && this.writer !== undefined;
}
public async sendPacketWaitResponse(packet: NiimbotPacket, timeoutMs: number = 1000): Promise<NiimbotPacket> {
if (this.port === undefined) {
throw new Error("Port is closed");
}
this.sendPacket(packet);
if (this.port.readable === null) {
throw new Error("Port is not readable");
}
let data = new Uint8Array();
let p: NiimbotPacket | undefined = undefined;
const reader = this.port.readable.getReader();
// todo: rewrite, no timeout!
try {
while (true) {
const { value, done } = await reader.read();
if (done) {
console.log("done");
break;
}
const newArr = new Uint8Array(data.length + value.length);
newArr.set(data);
newArr.set(value, data.length);
data = newArr;
try {
const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);
p = NiimbotPacket.fromBytes(dv);
break;
} catch (e) {
console.log("skipping");
}
// Do something with |value|...
}
} catch (error) {
console.error(error);
} finally {
reader.releaseLock();
}
console.log("end");
if (p === undefined) {
throw new Error("err");
}
// const reader: ReadableStreamDefaultReader<Uint8Array> = this.port.readable.getReader();
// const timer: NodeJS.Timeout = setTimeout(() => {
// reader.releaseLock();
// }, timeoutMs);
// const result: ReadableStreamReadResult<Uint8Array> = await reader.read();
// clearTimeout(timer);
// reader.releaseLock();
// const arr: Uint8Array = result.value!;
// console.log(Utils.bufToHex(arr));
// const dv = new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
// const inPacket = NiimbotPacket.fromBytes(dv);
// this.port.readable.pipeTo(new WritableStream({
// write(chunk) {
// console.log("Chunk received", chunk);
// },
// close() {
// console.log("All data successfully read!");
// },
// abort(e) {
// console.error("Something went wrong!", e);
// }
// }));
return p;
}
public async sendRaw(data: Uint8Array, force?: boolean) {
if (this.writer === undefined) {
throw new Error("Port is not writable");
}
// this.writer.releaseLock();
this.dispatchTypedEvent("rawpacketsent", new RawPacketSentEvent(data));
await Utils.sleep(2); // fixme maybe
}
}