@foxglove/ws-protocol-examples
Version:
Foxglove WebSocket protocol examples
107 lines • 4.27 kB
JavaScript
;
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