TypeScript / JavaScript API

Koheron SDK V1 documentation. You are reading the documentation for the V1 branch. It uses CFG=.../config.mk, memory.yml, Linux FPGA Manager and device-tree overlays. It is not backward-compatible with 0.x instruments.

Goal

Build a browser or Node client for a running instrument. The TypeScript client communicates with koheron-server over WebSockets and uses the generated drivers.json command metadata.

A web interface usually contains:

  1. HTML and CSS for the user interface.
  2. TypeScript wrappers for C++ drivers.
  3. Application code that connects UI events to instrument commands.

Add web files to an instrument

The top-level Makefile already initializes WEB_FILES with the shared SDK files web/main.css and web/koheron.ts. Add instrument-specific files in config.mk:

WEB_FILES += $(PROJECT_PATH)/web/index.html
WEB_FILES += $(PROJECT_PATH)/web/instrument.ts
WEB_FILES += $(PROJECT_PATH)/web/app.ts
WEB_FILES += $(PROJECT_PATH)/web/main.css

The web build runs tsc in the SDK web Docker image (koheron-web:node20 by default), targets ES5 output, writes TypeScript output to tmp/<project>/web/app.js, and copies non-TypeScript web assets into tmp/<project>/web/ before they are packaged in the instrument archive. Asset basenames must be unique because the archive is packaged flat.

Initialize the client

const client = new Client(location.hostname, 5);

window.addEventListener('load', async () => {
    await client.init();
    // create drivers and UI controllers here
});

window.onbeforeunload = () => {
    client.exit();
};

The second Client argument is the WebSocket pool size.

Write a TypeScript driver wrapper

A TypeScript wrapper maps a C++ driver class to client commands.

class FFT {
    private driver: Driver;
    private id: number;
    private cmds: HashTable<ICommand>;

    constructor(private client: Client) {
        this.driver = this.client.getDriver('FFT');
        this.id = this.driver.id;
        this.cmds = this.driver.getCmds();
    }

    setInputChannel(channel: number): void {
        this.client.send(Command(this.id, this.cmds['set_input_channel'], channel));
    }

    getFftSize(): Promise<number> {
        return this.client.readUint32(Command(this.id, this.cmds['get_fft_size']));
    }

    readPsd(): Promise<Float32Array> {
        return this.client.readFloat32Array(Command(this.id, this.cmds['read_psd']));
    }
}

The driver name and command names must match the exported C++ class and public method names in drivers.json.

Read command results

Read helpers support Promise-style use:

const fftSize = await fft.getFftSize();

and callback-style use where supported by the read helper:

client.readUint32(Command(id, cmds['get_fft_size']), value => {
    console.log(value);
});

Use a read helper that matches the C++ return type:

  • uint32_t: readUint32()
  • int32_t: readInt32()
  • float: readFloat32()
  • double: readFloat64()
  • bool: readBool()
  • std::array<uint32_t, N>: readUint32Array()
  • std::array<int32_t, N>: readInt32Array()
  • std::array<float, N>: readFloat32Array()
  • std::array<double, N>: readFloat64Array()
  • std::vector<uint32_t>: readUint32Vector()
  • std::vector<float>: readFloat32Vector()
  • std::vector<double>: readFloat64Vector()
  • std::tuple<...>: readTuple(cmd, fmt)

Application skeleton

class App {
    private fft: FFT;

    constructor(private window: Window, private document: Document, private ip: string) {
        const client = new Client(ip, 5);

        window.addEventListener('load', async () => {
            await client.init();
            this.fft = new FFT(client);
            console.log(await this.fft.getFftSize());
        });

        window.onbeforeunload = () => {
            client.exit();
        };
    }
}

const app = new App(window, document, location.hostname);

Dedicated sockets

The WebSocket pool supports dedicated sockets for long-running tasks. Use the shared pool for normal short commands and dedicated sockets for streams or operations that should not block other UI actions.

See also

[email protected]