From 70a2f47e32bed0e4d65f9ee12f7a5b348b9b6690 Mon Sep 17 00:00:00 2001 From: martha-johnston Date: Thu, 2 Jan 2025 21:43:34 +0100 Subject: [PATCH 1/2] add discover resources --- src/services/discovery.ts | 2 + src/services/discovery/client.spec.ts | 51 ++++++++++++++++++++++ src/services/discovery/client.ts | 61 +++++++++++++++++++++++++++ src/services/discovery/discovery.ts | 17 ++++++++ 4 files changed, 131 insertions(+) create mode 100644 src/services/discovery.ts create mode 100644 src/services/discovery/client.spec.ts create mode 100644 src/services/discovery/client.ts create mode 100644 src/services/discovery/discovery.ts diff --git a/src/services/discovery.ts b/src/services/discovery.ts new file mode 100644 index 000000000..529d9db3e --- /dev/null +++ b/src/services/discovery.ts @@ -0,0 +1,2 @@ +export { DiscoveryClient } from './discovery/client'; +export type { Discovery } from './discovery/discovery'; diff --git a/src/services/discovery/client.spec.ts b/src/services/discovery/client.spec.ts new file mode 100644 index 000000000..45acfa24b --- /dev/null +++ b/src/services/discovery/client.spec.ts @@ -0,0 +1,51 @@ +// @vitest-environment happy-dom + +import { + createPromiseClient, + createRouterTransport, +} from '@connectrpc/connect'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { DiscoveryService } from '../../gen/service/discovery/v1/discovery_connect'; +import { + DiscoverResourcesRequest, + DiscoverResourcesResponse, +} from '../../gen/service/discovery/v1/discovery_pb'; +import { RobotClient } from '../../robot'; +import { DiscoveryClient } from './client'; +import { ComponentConfig } from '../../gen/app/v1/robot_pb'; +vi.mock('../../robot'); +vi.mock('../../gen/service/discovery/v1/discovery_pb_service'); + +const discoveryClientName = 'test-discovery'; + +let discovery: DiscoveryClient; + +const discoveries: ComponentConfig = new ComponentConfig(); + +describe('DiscoveryClient Tests', () => { + beforeEach(() => { + const mockTransport = createRouterTransport(({ service }) => { + service(DiscoveryService, { + discoverResources: () => + new DiscoverResourcesResponse({ discovery: [discoveries] }), + }); + }); + + RobotClient.prototype.createServiceClient = vi + .fn() + .mockImplementation(() => + createPromiseClient(DiscoveryService, mockTransport) + ); + discovery = new DiscoveryClient(new RobotClient('host'), discoveryClientName); + }); + + describe('Discovery Resources Tests', () => { + it('returns resources from a machine', async () => { + const expected = [discoveries]; + + await expect( + discovery.discoverResources('discovery') + ).resolves.toStrictEqual(expected); + }); + }); +}); diff --git a/src/services/discovery/client.ts b/src/services/discovery/client.ts new file mode 100644 index 000000000..7e4ff2207 --- /dev/null +++ b/src/services/discovery/client.ts @@ -0,0 +1,61 @@ +import { Struct, type JsonValue } from '@bufbuild/protobuf'; +import type { CallOptions, PromiseClient } from '@connectrpc/connect'; +import { DiscoveryService } from '../../gen/service/discover/v1/discovery_connect'; +import { + DiscoverResourcesRequest, + DiscoverResourcesResponse, +} from '../../gen/service/discovery/v1/discovery_pb'; +import type { RobotClient } from '../../robot'; +import { doCommandFromClient } from '../../utils'; +import type { Discovery } from './discovery'; + +/** + * A gRPC-web client for a Vision service. + * + * @group Clients + */ +export class DiscoveryClient implements Discovery { + private client: PromiseClient; + private readonly name: string; + private readonly options: Options; + public callOptions: CallOptions = { headers: {} as Record }; + + constructor(client: RobotClient, name: string, options: Options = {}) { + this.client = client.createServiceClient(DiscoveryService); + this.name = name; + this.options = options; + } + + async discoverResources( + discoveryName: string, + extra = {}, + callOptions = this.callOptions + ) { + const request = new DiscoverResourcesRequest({ + name: this.name, + discoveryName, + extra: Struct.fromJson(extra), + }); + + this.options.requestLogger?.(request); + + const resp = await this.client.discoverResources( + request, + callOptions + ); + return resp.discovery; + } + + async doCommand( + command: Struct, + callOptions = this.callOptions + ): Promise { + return doCommandFromClient( + this.client.doCommand, + this.name, + command, + this.options, + callOptions + ); + } +} diff --git a/src/services/discovery/discovery.ts b/src/services/discovery/discovery.ts new file mode 100644 index 000000000..b8459f815 --- /dev/null +++ b/src/services/discovery/discovery.ts @@ -0,0 +1,17 @@ +import type { Struct } from '@bufbuild/protobuf'; +import type { Resource } from '../../types'; +import type { ComponentConfig } from '../../gen/app/v1/robot_pb'; + +/** A service that enables various computer vision algorithms */ +export interface Discovery extends Resource { + /** + * Get a list of detections in the next image given a camera. + * + * @param discoveryName - The name of the discovery service. + * @returns - The list of ComponentConfigs. + */ + discoverResources: ( + discoveryName: string, + extra?: Struct + ) => Promise; +} From eb0c6a86fbccbd1afbc403b86bf8b66cefe2b445 Mon Sep 17 00:00:00 2001 From: martha-johnston Date: Thu, 2 Jan 2025 21:48:54 +0100 Subject: [PATCH 2/2] add models from modules --- src/robot/client.ts | 7 +++++++ src/robot/robot.ts | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/robot/client.ts b/src/robot/client.ts index f845bc0a1..580b6d94f 100644 --- a/src/robot/client.ts +++ b/src/robot/client.ts @@ -701,6 +701,13 @@ export class RobotClient extends EventDispatcher implements Robot { return resp.discovery; } + // GET MODELS FROM MODULES + + async getModelsFromModules() { + const resp = await this.robotService.getModelsFromModules(); + return resp.model; + } + // GET CLOUD METADATA async getCloudMetadata() { diff --git a/src/robot/robot.ts b/src/robot/robot.ts index f279e826f..dcaecc2fe 100644 --- a/src/robot/robot.ts +++ b/src/robot/robot.ts @@ -2,6 +2,7 @@ import type { Struct } from '@bufbuild/protobuf'; import { MachineConnectionEvent } from '../events'; import type { PoseInFrame, Transform } from '../gen/common/v1/common_pb'; import type proto from '../gen/robot/v1/robot_pb'; +import type { ComponentConfig } from '../gen/app/v1/robot_pb'; import type { ResourceName } from '../types'; export type CloudMetadata = proto.GetCloudMetadataResponse; @@ -113,6 +114,15 @@ export interface Robot { queries: proto.DiscoveryQuery[] ): Promise; + /** + * Get the list of discovered component configurations. + * + * @group ComponentConfig + * @alpha + */ + getModelsFromModules( + ): Promise; + /** * Get a list of all resources on the robot. *