Norse Polytheistic Mythology

    @foxglove/ws-protocol
    TypeScript icon, indicating that this package has built-in type declarations

    0.4.0 • Public • Published

    Foxglove WebSocket server and client

    This package provides a server implementation of the Foxglove WebSocket protocol. This protocol enables Foxglove Studio to ingest arbitrary “live” streamed data.

    Installation

    $ npm install @foxglove/ws-protocol
    

    This package does not require a specific WebSocket server or client implementation, so you will need to install your own. For Node.js, you can use the ws package:

    $ npm install ws
    

    Examples

    Run these example scripts, implemented in TypeScript, to get started.

    Server template

    The template below publishes messages on a single topic called example_msg, using JSON to encode message data and JSON Schema to describe the message layout.

    const { FoxgloveServer } = require("@foxglove/ws-protocol");
    const { WebSocketServer } = require("ws");
    
    function delay(durationSec) {
      return new Promise((resolve) => setTimeout(resolve, durationSec * 1000));
    }
    
    async function main() {
      const server = new FoxgloveServer({ name: "example-server" });
      const ws = new WebSocketServer({
        port: 8765,
        handleProtocols: (protocols) => server.handleProtocols(protocols),
      });
      ws.on("listening", () => {
        console.log("server listening on %s", ws.address());
      });
      ws.on("connection", (conn, req) => {
        const name = `${req.socket.remoteAddress}:${req.socket.remotePort}`;
        console.log("connection from %s via %s", name, req.url);
        server.handleConnection(conn, name);
      });
      server.on("subscribe", (chanId) => {
        console.log("first client subscribed to %d", chanId);
      });
      server.on("unsubscribe", (chanId) => {
        console.log("last client unsubscribed from %d", chanId);
      });
      server.on("error", (err) => {
        console.error("server error: %o", err);
      });
    
      const ch1 = server.addChannel({
        topic: "example_msg",
        encoding: "json",
        schemaName: "ExampleMsg",
        schema: JSON.stringify({
          type: "object",
          properties: {
            msg: { type: "string" },
            count: { type: "number" },
          },
        }),
      });
    
      const textEncoder = new TextEncoder();
      let i = 0;
      while (true) {
        await delay(0.2);
        server.sendMessage(
          ch1,
          BigInt(Date.now()) * 1_000_000n,
          textEncoder.encode(JSON.stringify({ msg: "Hello!", count: ++i })),
        );
      }
    }
    
    main().catch(console.error);

    Copy the template code into a file and run it (e.g. node server.js). Then, make the necessary adjustments to the file to customize this simple server to your desired specifications.

    Client template

    The template below subscribes to messages on all channels that use the json encoding. See @foxglove/ws-protocol-examples for an example client that subscribes to messages with the protobuf encoding.

    const { FoxgloveClient } = require("@foxglove/ws-protocol");
    const { WebSocket } = require("ws");
    
    async function main() {
      const client = new FoxgloveClient({
        ws: new WebSocket(`ws://localhost:8765`, [FoxgloveClient.SUPPORTED_SUBPROTOCOL]),
      });
      const deserializers = new Map();
      client.on("advertise", (channels) => {
        for (const channel of channels) {
          if (channel.encoding !== "json") {
            console.warn(`Unsupported encoding ${channel.encoding}`);
            continue;
          }
          const subId = client.subscribe(channel.id);
          const textDecoder = new TextDecoder();
          deserializers.set(subId, (data) => JSON.parse(textDecoder.decode(data)));
        }
      });
      client.on("message", ({ subscriptionId, timestamp, data }) => {
        console.log({
          subscriptionId,
          timestamp,
          data: deserializers.get(subscriptionId)(data),
        });
      });
    }
    
    main().catch(console.error);

    Copy the template code into a file (e.g. client.js) and start up a Foxglove Websocket server. In a separate terminal window, run the client code (e.g. node client.js).

    You should see the following output if both your server and client are running correctly:

    $ node client.js
    {
      subscriptionId: 0,
      timestamp: 1638999307183000000n,
      data: { msg: 'Hello!', count: 2849 }
    }
    {
      subscriptionId: 0,
      timestamp: 1638999307384000000n,
      data: { msg: 'Hello!', count: 2850 }
    }
    ...
    

    Make the necessary adjustments to the file to customize this simple client.

    Development

    This package lives inside a monorepo that uses yarn workspaces, so most commands (other than yarn install) should be prefixed with yarn workspace @foxglove/ws-protocol ....

    • yarn install – Install development dependencies
    • yarn workspace @foxglove/ws-protocol version --patch (or --minor or --major) – Increment the version number and create the appropriate git tag

    Install

    npm i @foxglove/ws-protocol

    DownloadsWeekly Downloads

    1,056

    Version

    0.4.0

    License

    MIT

    Unpacked Size

    276 kB

    Total Files

    63

    Last publish

    Collaborators

    • foxglovebot
    • amacneil