SlimeVR Server Documentation

repository·main·Indexed 21 days ago

https://github.com/slimevr/slimevr-server

Central orchestration hub for the SlimeVR ecosystem. It manages communication between tracking sensors—including ESP-based trackers, owoTrack mobile apps, and SlimeVR Wrangler (Joycons)—and software integrations such as SteamVR, VRChat, and VSeeFace. The server supports portable configuration mode, an Electron-based GUI with CLI options, and a firmware tool API for building and managing firmware compatibility.

Tokens
4.3K
Snippets
18
Records
22
Agent score
76%

What's inside SlimeVR Server

  1. Overview of SlimeVR Server

    main

    SlimeVR Server is the central orchestration application for the SlimeVR ecosystem. It manages communication between various hardware sensors and software integrations.

    Supported Sensor Implementations

    • SlimeVR Tracker for ESP: Supports ESP microcontrollers and multiple IMUs.
    • owoTrack Mobile App: Allows using mobile phones as trackers (note: limited functionality and compatibility).
    • SlimeVR Wrangler: Allows using Nintendo Switch Joycon controllers as trackers.

    Software Integrations

    • SteamVR: Use the SlimeVR OpenVR Driver to integrate with SteamVR.
    • VRChat / PCVR / Standalone: Use built-in OSC Trackers support for Full Body Tracking (FBT).
    • VSeeFace & Other Apps: Use built-in VMC support to send and receive tracking data.
    • 3D Applications (e.g., Blender): Export recordings as .BVH files to import motion capture data.
  2. Use portable configuration mode in SlimeVR Server

    main
    SlimeVR Server supports a portable configuration mode. When enabled, the server saves its configuration files in the same directory as the server executable/binary, rather than in the standard user configuration folder. This is useful for running the server from removable drives or keeping all server-related files in a single, self-contained directory.
  3. Configure openapi-codegen for the firmware-tool API

    main

    The openapi-codegen.config.ts file defines how the OpenAPI schema for the firmware tool is transformed into TypeScript types and React Query components.

    It uses defineConfig from @openapi-codegen/cli and relies on the following configuration structure:

    • firmwareTool.from.source: Set to 'url' to indicate the schema is fetched from a remote endpoint.
    • firmwareTool.from.url: The URL of the OpenAPI JSON schema. This is pulled from the FIRMWARE_TOOL_SCHEMA_URL environment variable, defaulting to http://localhost:3000/api-json.
    • firmwareTool.outputDir: The directory where generated files are stored (src/firmware-tool-api).
    • firmwareTool.to: An asynchronous function that executes the generation logic using @openapi-codegen/typescript utilities:
      1. generateSchemaTypes: Generates TypeScript schema types using a specified filenamePrefix (set to firmwareTool).
      2. generateReactQueryComponents: Generates React Query hooks/components using the same prefix and the files produced by generateSchemaTypes.
    export default defineConfig({
      firmwareTool: {
        from: {
          source: 'url',
          url: process.env.FIRMWARE_TOOL_SCHEMA_URL ?? 'http://localhost:3000/api-json',
        },
        outputDir: 'src/firmware-tool-api',
        to: async (context) => {
          const filenamePrefix = 'firmwareTool';
          const { schemasFiles } = await generateSchemaTypes(context, {
            filenamePrefix,
          });
          await generateReactQueryComponents(context, {
            filenamePrefix,
            schemasFiles,
          });
        },
      },
    });
  4. Get detailed firmware info with `useGetFirmwareId`

    main

    Retrieves comprehensive information about a specific firmware using its unique ID. Unlike the basic list, this provides detailed data including pins, IMU configurations, and associated files.

    Variables:

    • pathParams.id: The unique firmware ID.

    Response: Returns Schemas.FirmwareWithFiles.

    const { data: firmwareDetails } = useGetFirmwareId({
      pathParams: { id: 'some-uuid-123' }
    });
  5. Build firmware with `usePostFirmwareBuild`

    main

    Triggers a new firmware build process. This is a mutation hook.

    Variables:

    • body: An object of type Schemas.BuildFirmwareBody containing the build configuration.

    Response: Returns either Schemas.BuildStatusBasic or Schemas.BuildStatusDone upon completion.

    const buildMutation = usePostFirmwareBuild();
    
    const handleBuild = async (config: Schemas.BuildFirmwareBody) => {
      try {
        const result = await buildMutation.mutateAsync({ body: config });
        console.log('Build finished:', result);
      } catch (error) {
        console.error('Build failed', error);
      }
    };
  6. Check firmware compatibility with `useGetIsCompatibleVersion`

    main

    Use this hook to determine if a specific server version is compatible with the current firmware API. It returns a success status or a reason containing a message and compatible versions.

    Variables:

    • pathParams.version: The version string to check.
    • fetcherOptions: Standard firmware tool fetcher options from context.

    Response Shape:

    • { success: true }
    • { success: false, reason: { message: string, versions: string } }
    const { data, isLoading } = useGetIsCompatibleVersion(
      { pathParams: { version: '20.1.0' } }
    );
    
    if (data && !data.success) {
      console.log(data.reason.message);
    }
  7. Access global application state with useAppContext

    main

    The useAppContext hook provides access to the global application context. It is used to retrieve information about the current firmware release. This hook must be used within a component that is a child of the provider created by useProvideAppContext.

    Note: If called outside of an AppContext provider, it will throw an error: useAppContext must be within a AppContext Provider.

    import { useAppContext } from './hooks/app';
    
    function MyComponent() {
      const { currentFirmwareRelease } = useAppContext();
    
      return (
        <div>
          Current Firmware: {currentFirmwareRelease?.version ?? 'Unknown'}
        </div>
      );
    }
  8. Initialize application context with useProvideAppContext

    main

    The useProvideAppContext hook is a provider-level hook responsible for initializing the application's core lifecycle. It performs several critical background tasks:

    1. Data Feed Initialization: When connected to the websocket, it sends a StartDataFeed packet containing dataFeedConfig and bonesDataFeedConfig.
    2. Data Synchronization: It listens for DataFeedUpdate packets to update the global datafeedAtom and bonesAtom stores.
    3. Firmware Polling: It polls the server every 1000ms using fetchCurrentFirmwareRelease(config.uuid) to keep the currentFirmwareRelease state up to date.
    4. Localization: It synchronizes the application locale with the user's config.lang.
    5. Error Tracking: It initializes Sentry error tracking based on the config.errorTracking setting.
    6. Audio Feedback: It handles reset sounds via RpcMessage.ResetResponse if config.feedbackSound is enabled.

    It returns an AppContext object containing the currentFirmwareRelease state.

    import { useProvideAppContext, useAppContext } from './hooks/app';
    
    function App() {
      // This hook sets up the providers and background processes
      const appContext = useProvideAppContext();
    
      return (
        <AppContextC value={appContext}>
          <MainContent />
        </AppContextC>
      );
    }
  9. Configure FirmwareToolContext for React Query wrappers

    main

    When building custom hooks or components that interface with the Firmware Tool API, you can use useFirmwareToolContext to access configuration for fetchers and query behavior. This context is designed to be used within React Query wrappers to standardize how headers, query parameters, and query keys are handled.

    Context Properties

    • fetcherOptions: Configuration for the underlying fetcher.
      • headers: An object of headers to inject into requests.
      • queryParams: An object of query parameters to inject into requests.
    • queryOptions:
      • enabled: A boolean to control automatic refetching. Defaults to true. Set to false to disable automatic refetching when the query mounts or when query keys change.
    • queryKeyFn: A function used to generate a unique QueryKey based on a QueryOperation.
    // Example of how the context structure is defined
    const context: FirmwareToolContext = {
      fetcherOptions: {
        headers: { 'Authorization': 'Bearer token' },
        queryParams: { 'version': '1.0' }
      },
      queryOptions: {
        enabled: true
      },
      queryKeyFn: (operation) => queryKeyFn(operation)
    };