Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/disco/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "",
"main": "build/index.js",
"scripts": {
"dev": "tsc -w",
"build": "tsc",
"start": "node .",
"build:start": "npm run build && npm run start"
Expand Down
16 changes: 11 additions & 5 deletions examples/disco/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
/* eslint-disable no-await-in-loop */
import { config } from "dotenv";
import { LighthouseAuth, LighthouseWebsocket } from "lighthouse.js";
import { LighthouseAuth, LighthouseWebsocket, LIGHTHOUSE_WIDTH, LIGHTHOUSE_HEIGHT } from "lighthouse.js";

config();

const user = process.env.LIGHTHOUSE_USER ?? "";
function getEnv(name: string): string {
const value = process.env[name];
if (!value) throw Error(`Environment variable ${name} is not defined!`);
return value;
}

const user = getEnv("LIGHTHOUSE_USER");

const auth: LighthouseAuth<typeof user> = {
USER: user,
TOKEN: process.env.LIGHTHOUSE_TOKEN ?? "",
TOKEN: getEnv("LIGHTHOUSE_TOKEN"),
};

async function sleep(time: number) {
Expand All @@ -24,8 +30,8 @@ async function sleep(time: number) {
// eslint-disable-next-line no-constant-condition
while (true) {
// eslint-disable-next-line no-loop-func
const data = new Array(28 * 14 * 3).fill(0).map((_, j) => (j % 3 === i ? 255 : 0));
const msg = await lh.send(data);
const data = new Uint8Array(LIGHTHOUSE_WIDTH * LIGHTHOUSE_HEIGHT * 3).map((_, j) => (j % 3 === i ? 255 : 0));
const msg = await lh.sendDisplay(data);

// eslint-disable-next-line no-console
console.log(msg);
Expand Down
64 changes: 0 additions & 64 deletions src/Lighthouse/LighthouseWebsocket.ts

This file was deleted.

2 changes: 2 additions & 0 deletions src/Lighthouse/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const LIGHTHOUSE_WIDTH: number = 28;
export const LIGHTHOUSE_HEIGHT: number = 14;
25 changes: 25 additions & 0 deletions src/Lighthouse/protocol.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export type LighthouseVerb = "POST" | "CREATE" | "MKDIR" | "DELETE" | "LIST" | "GET" | "PUT" | "STREAM" | "STOP" | "LINK" | "UNLINK";
export type LighthousePath<U extends string> = ["user", U, "model"];

export interface LighthouseAuth<U extends string> {
USER: U;
TOKEN: string;
}

export interface LighthouseRequest<U extends string, P> {
REID: string;
AUTH: LighthouseAuth<U>;
VERB: LighthouseVerb;
PATH: LighthousePath<U>;
META: object;
PAYL: P;
}

export interface LighthouseEvent<P> {
REID: string;
RNUM: number;
RESPONSE: string;
META: object;
PAYL: P;
WARNINGS: string[];
}
24 changes: 0 additions & 24 deletions src/Lighthouse/types.ts

This file was deleted.

85 changes: 85 additions & 0 deletions src/Lighthouse/websocket.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { decode, encode } from "@msgpack/msgpack";
import { v4 as uuid } from "uuid";
import { WebSocket } from "ws";
import { LighthouseAuth, LighthousePath, LighthouseRequest, LighthouseEvent, LighthouseVerb } from "./protocol";

type LighthouseEventHandler<P> = (event: LighthouseEvent<P>) => void;

export class LighthouseWebsocket<U extends string> {
private static readonly serverAddress = "wss://lighthouse.uni-kiel.de/websocket";

private ws?: WebSocket;

private responseHandlers: Map<string, LighthouseEventHandler<unknown>> = new Map();
private eventHandlers: LighthouseEventHandler<unknown>[] = [];

constructor(private readonly auth: LighthouseAuth<U>) {}

public async open(address = LighthouseWebsocket.serverAddress): Promise<number> {
this.ws = new WebSocket(address);

this.ws.on("message", (data) => {
const response = decode(new Uint8Array(data as Buffer)) as LighthouseEvent<unknown>;
const handler = this.responseHandlers.get(response.REID);
if (handler && typeof handler === "function") {
handler(response);
this.responseHandlers.delete(response.REID);
} else {
for (const handler of this.eventHandlers) {
handler(response);
}
}
});
return new Promise<number>((res) => {
this.ws?.once("open", (code: number) => {
res(code);
});
});
}

public async sendDisplay(rgbValues: Uint8Array): Promise<LighthouseEvent<unknown>> {
return await this.send("PUT", ["user", this.auth.USER, "model"], rgbValues);
}

public async requestStream(): Promise<LighthouseEvent<unknown>> {
return await this.send("STREAM", ["user", this.auth.USER, "model"], undefined);
}

private async send<P>(verb: LighthouseVerb, path: LighthousePath<U>, payload: P): Promise<LighthouseEvent<unknown>> {
const id = uuid();
const request: LighthouseRequest<U, P> = {
AUTH: this.auth,
META: {},
PATH: path,
PAYL: payload,
REID: id,
VERB: verb,
};
if (this.ws?.readyState === WebSocket.OPEN) {
const prom = new Promise<LighthouseEvent<unknown>>((resolve, reject) => {
this.registerResponseHandler(id, response => {
if (response.RNUM === 200) {
resolve(response);
} else {
reject(`${response.RNUM} ${response.RESPONSE}`);
}
});
});
this.ws?.send(encode(request));
return prom;
}
throw new Error("Websocket is currently not open!");
}

private registerResponseHandler<P>(id: string, cb: LighthouseEventHandler<P>): void {
this.responseHandlers.set(id, cb as LighthouseEventHandler<unknown>);
}

private registerEventHandler<P>(cb: LighthouseEventHandler<P>): void {
this.eventHandlers.push(cb as LighthouseEventHandler<unknown>);
}

public close(): void {
this.ws?.close();
}
}
5 changes: 3 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./Lighthouse/LighthouseWebsocket";
export * from "./Lighthouse/types";
export * from "./lighthouse/websocket";
export * from "./lighthouse/constants";
export * from "./lighthouse/protocol";