@foxglove/ws-protocol-examples
Version:
Foxglove WebSocket protocol examples
136 lines • 5.42 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const rosmsg_serialization_1 = require("@foxglove/rosmsg-serialization");
const ws_protocol_1 = require("@foxglove/ws-protocol");
const commander_1 = require("commander");
const debug_1 = tslib_1.__importDefault(require("debug"));
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:service-server");
debug_1.default.enable("foxglove:*");
async function main() {
const supportedEncodings = ["json", "ros1"];
const server = new ws_protocol_1.FoxgloveServer({
name: "service-server",
capabilities: [ws_protocol_1.ServerCapability.services],
supportedEncodings,
});
const port = 8765;
const ws = new ws_1.WebSocketServer({
port,
handleProtocols: (protocols) => server.handleProtocols(protocols),
});
(0, setupSigintHandler_1.setupSigintHandler)(log, ws);
const serviceDefRos = {
name: "/set_bool_ros",
type: "std_srvs/SetBool",
request: {
encoding: "ros1",
schemaName: "std_srvs/SetBool_Request",
schemaEncoding: "ros1msg",
schema: "bool data",
},
response: {
encoding: "ros1",
schemaName: "std_srvs/SetBool_Response",
schemaEncoding: "ros1msg",
schema: "bool success\nstring message",
},
};
const serviceDefJson = {
name: "/set_bool_json",
type: "std_srvs/SetBool",
request: {
encoding: "json",
schemaName: "SetBoolJsonRequest",
schemaEncoding: "jsonschema",
schema: JSON.stringify({
$schema: "https://json-schema.org/draft/2019-09/schema",
type: "object",
properties: {
data: { type: "boolean" },
},
}),
},
response: {
encoding: "json",
schemaName: "SetBoolJsonResponse",
schemaEncoding: "jsonschema",
schema: JSON.stringify({
$schema: "https://json-schema.org/draft/2019-09/schema",
type: "object",
properties: {
success: { type: "boolean" },
message: { type: "string" },
},
}),
},
};
const serviceById = new Map([
[server.addService(serviceDefRos), serviceDefRos],
[server.addService(serviceDefJson), serviceDefJson],
]);
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("serviceCallRequest", (request, clientConnection) => {
const service = serviceById.get(request.serviceId);
if (!service) {
const err = new Error(`Received invalid serviceId: "${request.serviceId}"`);
server.sendServiceCallFailure({
op: "serviceCallFailure",
serviceId: request.serviceId,
callId: request.callId,
message: err.message,
}, clientConnection);
throw err;
}
if (service.request.encoding !== request.encoding) {
const err = new Error(`Service ${service.name} called with invalid message encoding. Expected ${service.request.encoding}, got ${request.encoding}`);
server.sendServiceCallFailure({
op: "serviceCallFailure",
serviceId: request.serviceId,
callId: request.callId,
message: err.message,
}, clientConnection);
throw err;
}
log("Received service call request with %d bytes", request.data.byteLength);
const responseMsg = {
success: true,
message: `Service ${service.name} successfully called`,
};
let responseData = new Uint8Array();
if (request.encoding === "json") {
responseData = new Uint8Array(Buffer.from(JSON.stringify(responseMsg)));
}
else {
const definitions = [
{ name: "success", type: "bool" },
{ name: "message", type: "string" },
];
const writer = new rosmsg_serialization_1.MessageWriter([{ definitions }]);
responseData = writer.writeMessage(responseMsg);
}
const response = {
...request,
data: responseData,
};
server.sendServiceCallResponse(response, clientConnection);
});
server.on("error", (err) => {
log("server error: %o", err);
});
}
exports.default = new commander_1.Command("service-server")
.description("advertises a ROS1 and JSON SetBool service that can be called")
.action(main);
//# sourceMappingURL=service-server.js.map