UNPKG

@foxglove/ws-protocol-examples

Version:

Foxglove WebSocket protocol examples

107 lines 4.27 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const rostime_1 = require("@foxglove/rostime"); const jsonschema_1 = require("@foxglove/schemas/jsonschema"); const ws_protocol_1 = require("@foxglove/ws-protocol"); const commander_1 = require("commander"); const debug_1 = tslib_1.__importDefault(require("debug")); const PImage = tslib_1.__importStar(require("pureimage")); const stream_1 = require("stream"); const ws_1 = require("ws"); const boxen_1 = tslib_1.__importDefault(require("../boxen")); const setupSigintHandler_1 = require("./util/setupSigintHandler"); const log = (0, debug_1.default)("foxglove:image-server"); debug_1.default.enable("foxglove:*"); // eslint-disable-next-line @typescript-eslint/promise-function-async function delay(durationMs) { return new Promise((resolve) => setTimeout(resolve, durationMs)); } function drawImage(time) { const width = 200; const height = 150; const image = PImage.make(width, height); const ctx = image.getContext("2d"); ctx.fillStyle = "#eeeeee"; ctx.fillRect(0, 0, width, height); ctx.fillStyle = "#cc2222"; ctx.beginPath(); ctx.arc(width * (0.2 + 0.15 * Math.sin(time * 0.001)), 40, 30, 0, 2 * Math.PI, false); ctx.fill(); ctx.save(); ctx.fillStyle = "#3344ee"; ctx.beginPath(); ctx.translate(width * 0.5, height * 0.7); const w = Math.sin(time * 0.001) * 0.1 + 0.4; const h = Math.cos(time * 0.001) * 0.1 + 0.3; ctx.rect((-width * w) / 2, (-height * h) / 2, width * w, height * h); ctx.fill(); ctx.restore(); ctx.save(); ctx.fillStyle = "#22cc44"; ctx.translate(width * 0.6, height * 0.5); ctx.rotate(time * 0.0005); ctx.beginPath(); ctx.moveTo(width * -0.1, height * 0.1); ctx.lineTo(width * 0.2, height * 0.2); ctx.lineTo(width * 0, height * -0.2); ctx.fill(); ctx.restore(); return image; } async function main() { const server = new ws_protocol_1.FoxgloveServer({ name: "image-server" }); const port = 8765; const ws = new ws_1.WebSocketServer({ port, handleProtocols: (protocols) => server.handleProtocols(protocols), }); const signal = (0, setupSigintHandler_1.setupSigintHandler)(log, ws); ws.on("listening", () => { void (0, boxen_1.default)(`📡 Server listening on localhost:${port}. To see data, visit:\n` + `https://app.foxglove.dev/~/view?ds=foxglove-websocket&ds.url=ws://localhost:${port}/`, { borderStyle: "round", padding: 1 }).then(log); }); ws.on("connection", (conn, req) => { const name = `${req.socket.remoteAddress}:${req.socket.remotePort}`; log("connection from %s via %s", name, req.url); server.handleConnection(conn, name); }); server.on("subscribe", (chanId) => { log("first client subscribed to %d", chanId); }); server.on("unsubscribe", (chanId) => { log("last client unsubscribed from %d", chanId); }); server.on("error", (err) => { log("server error: %o", err); }); const ch1 = server.addChannel({ topic: "example_image", encoding: "json", schemaName: jsonschema_1.CompressedImage.title, schema: JSON.stringify(jsonschema_1.CompressedImage), }); const textEncoder = new TextEncoder(); while (!signal.aborted) { await delay(50); const image = drawImage(Date.now()); const chunks = []; const writable = new stream_1.Writable(); // eslint-disable-next-line no-underscore-dangle writable._write = (chunk, _encoding, callback) => { chunks.push(chunk); callback(); }; await PImage.encodeJPEGToStream(image, writable, 90); const now = BigInt(Date.now()) * 1000000n; server.sendMessage(ch1, now, textEncoder.encode(JSON.stringify({ timestamp: (0, rostime_1.fromNanoSec)(now), encoding: "jpeg", data: Buffer.concat(chunks).toString("base64"), }))); } } exports.default = new commander_1.Command("image-server") .description("generate images and publish them as base64-encoded binary in JSON") .action(main); //# sourceMappingURL=image-server.js.map