156 lines
4.3 KiB
TypeScript
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
|
|
}
|
|
}
|