@blueyerobotics/blueye-ts 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,9 +20,9 @@ export declare class BlueyeClient {
20
20
  private wsReqRep;
21
21
  private isReqRepConnected;
22
22
  private logger;
23
+ private pendingRequests;
23
24
  sub: Emitter<Events>;
24
25
  constructor(logLevel?: LogLevel);
25
- private send;
26
26
  sendRequest<T extends Req>(req: T, opts?: CreateArgs<T>): Promise<DecodedOutput<T> | null>;
27
27
  getTelemetry<T extends Tel>(type: T): Promise<DecodedTelOutput<T>>;
28
28
  }
@@ -5,6 +5,7 @@ const protocol_definitions_1 = require("@blueyerobotics/protocol-definitions");
5
5
  const buffer_1 = require("buffer");
6
6
  const consola_1 = require("consola");
7
7
  const strict_event_emitter_1 = require("strict-event-emitter");
8
+ const uuid_1 = require("uuid");
8
9
  const schema_1 = require("./schema");
9
10
  const WS_PUBSUB_URL = "ws://localhost:8765";
10
11
  const WS_REQREP_URL = "ws://localhost:8766";
@@ -17,6 +18,7 @@ class BlueyeClient {
17
18
  wsReqRep;
18
19
  isReqRepConnected = false;
19
20
  logger;
21
+ pendingRequests = new Map();
20
22
  sub = new strict_event_emitter_1.Emitter();
21
23
  constructor(logLevel = consola_1.LogLevels.info) {
22
24
  this.logger = (0, consola_1.createConsola)({ level: logLevel, formatOptions: { colors: true, compact: false } });
@@ -36,41 +38,36 @@ class BlueyeClient {
36
38
  this.logger.verbose("[WS] PubSub message:", key, message);
37
39
  this.sub.emit(key, message);
38
40
  });
39
- }
40
- async send(data) {
41
- while (!this.isReqRepConnected) {
42
- this.logger.debug("Waiting...");
43
- await new Promise(res => setTimeout(res, 50));
44
- }
45
- return await new Promise((resolve, reject) => {
46
- const onMessage = (event) => {
47
- cleanUp();
48
- resolve(event.data);
49
- };
50
- const onError = (error) => {
51
- cleanUp();
52
- this.logger.error("[WS] Error:", error);
53
- reject(error);
54
- };
55
- const cleanUp = () => {
56
- this.wsReqRep.removeEventListener("message", onMessage);
57
- this.wsReqRep.removeEventListener("error", onError);
58
- };
59
- this.wsReqRep.addEventListener("message", onMessage);
60
- this.wsReqRep.addEventListener("error", onError);
61
- this.wsReqRep.send(data);
41
+ this.wsReqRep.addEventListener("message", event => {
42
+ this.logger.debug("Response:", event.data);
43
+ const { id, key, data } = schema_1.responseSchema.parse(JSON.parse(event.data));
44
+ if (!id)
45
+ throw new Error("Response id is missing");
46
+ this.pendingRequests.get(id)?.({ key, data });
47
+ this.pendingRequests.delete(id);
62
48
  });
63
49
  }
64
50
  async sendRequest(req, opts = {}) {
65
51
  const protocol = protocol_definitions_1.blueye.protocol[req];
66
52
  const message = protocol.create(opts);
67
53
  const encoded = protocol.encode(message).finish();
68
- const response = await this.send(JSON.stringify({
69
- key: `blueye.protocol.${req}`,
70
- data: buffer_1.Buffer.from(encoded).toString("base64")
71
- }));
72
- this.logger.debug("Response:", response);
73
- const { key, data } = schema_1.responseSchema.parse(JSON.parse(response));
54
+ while (!this.isReqRepConnected) {
55
+ this.logger.debug("Waiting...");
56
+ await new Promise(res => setTimeout(res, 50));
57
+ }
58
+ const { key, data } = await Promise.race([
59
+ new Promise((_, reject) => setTimeout(() => reject(new Error("Request timed out")), 2000)),
60
+ new Promise(resolve => {
61
+ const id = (0, uuid_1.v4)();
62
+ const request = JSON.stringify({
63
+ id,
64
+ key: `blueye.protocol.${req}`,
65
+ data: buffer_1.Buffer.from(encoded).toString("base64")
66
+ });
67
+ this.pendingRequests.set(id, resolve);
68
+ this.wsReqRep.send(request);
69
+ })
70
+ ]);
74
71
  if (key === "Empty") {
75
72
  return null;
76
73
  }
@@ -1,14 +1,17 @@
1
1
  import { Buffer } from "buffer";
2
2
  import z from "zod";
3
3
  export declare const responseSchema: z.ZodObject<{
4
+ id: z.ZodOptional<z.ZodString>;
4
5
  key: z.ZodEffects<z.ZodString, string, string>;
5
6
  data: z.ZodEffects<z.ZodString, Buffer, string>;
6
7
  }, "strip", z.ZodTypeAny, {
7
8
  key: string;
8
9
  data: Buffer;
10
+ id?: string | undefined;
9
11
  }, {
10
12
  key: string;
11
13
  data: string;
14
+ id?: string | undefined;
12
15
  }>;
13
16
  export declare const telemetrySchema: z.ZodObject<{
14
17
  payload: z.ZodObject<{
@@ -7,6 +7,7 @@ exports.telemetrySchema = exports.responseSchema = void 0;
7
7
  const buffer_1 = require("buffer");
8
8
  const zod_1 = __importDefault(require("zod"));
9
9
  exports.responseSchema = zod_1.default.object({
10
+ id: zod_1.default.string().uuid().optional(),
10
11
  key: zod_1.default.string().transform(val => val.split(".").at(-1)),
11
12
  data: zod_1.default
12
13
  .string()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blueyerobotics/blueye-ts",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A TypeScript client for interacting with Blueye underwater drones.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -17,11 +17,13 @@
17
17
  },
18
18
  "keywords": [],
19
19
  "author": "Blueye <contact@blueye.no> (https://blueye.no/)",
20
+ "license": "LGPL-3.0-only",
20
21
  "dependencies": {
21
22
  "@blueyerobotics/protocol-definitions": "3.2.0-3e0ba702",
22
23
  "buffer": "^6.0.3",
23
24
  "consola": "^3.4.2",
24
25
  "strict-event-emitter": "^0.5.1",
26
+ "uuid": "^11.1.0",
25
27
  "zod": "^3.25.67"
26
28
  },
27
29
  "devDependencies": {