Skip to content

Tryanks/virtualhere-go

Repository files navigation

virtualhere-go

A Go library for controlling VirtualHere USB clients programmatically.

Overview

virtualhere-go provides a Go interface to interact with VirtualHere USB client software, allowing you to manage USB devices shared over the network. It communicates with the VirtualHere client daemon through platform-specific IPC mechanisms:

  • Windows: Named pipe (\\.\pipe\vhclient)
  • Linux/macOS: Unix domain sockets (/tmp/vhclient and /tmp/vhclient_response)

Features

  • Control VirtualHere USB client from Go applications
  • List available USB servers and devices
  • Use and stop using remote USB devices
  • Manage server connections and auto-use settings
  • Run client as a background service/daemon
  • Parse command responses into structured data
  • Support for all VirtualHere API commands

Installation

go get github.com/Tryanks/virtualhere-go

Requirements

Usage

Starting the VirtualHere Client Daemon

Before using this library, you need to start the VirtualHere client as a daemon:

Linux:

# Start the daemon
sudo ./vhclientx86_64 -n

# Or use systemd (recommended)
sudo systemctl start virtualhereclient.service

macOS:

# Run the client in background
./vhclient &

Windows:

# Install as service (requires admin rights)
vhui64.exe -i

# Or just run the GUI client (it creates the named pipe automatically)
vhui64.exe

Basic Example (Recommended)

The simplest way to use the library is with NewPipeClient(), which connects to an already-running VirtualHere service:

package main

import (
    "fmt"
    "log"

    vh "github.com/Tryanks/virtualhere-go"
)

func main() {
    // Create a pipe client (connects to running VirtualHere service)
    // No binary path needed - uses platform-specific IPC automatically
    client, err := vh.NewPipeClient()
    if err != nil {
        log.Fatal(err)
    }

    // List all available hubs and devices
    state, err := client.List()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Auto-Find: %v\n", state.AutoFindEnabled)
    fmt.Printf("Running as Service: %v\n\n", state.RunningAsService)

    for _, hub := range state.Hubs {
        fmt.Printf("Hub: %s (%s)\n", hub.Name, hub.Address)
        for _, device := range hub.Devices {
            fmt.Printf("  - %s (%s) [In Use: %v]\n",
                device.Name, device.Address, device.InUse)
        }
    }

    // Use a device
    err = client.Use("raspberrypi.114", "")
    if err != nil {
        log.Fatal(err)
    }

    // Stop using a device
    err = client.StopUsing("raspberrypi.114")
    if err != nil {
        log.Fatal(err)
    }
}

Alternative: Using NewClient with Binary Path

If you need to manage the VirtualHere service lifecycle or need the binary path:

client, err := vh.NewClient("/path/to/vhclient")
if err != nil {
    log.Fatal(err)
}
// Use the client same as above...

Running Client as a Managed Service

You can also let the library manage the VirtualHere client process:

package main

import (
    "fmt"
    "log"

    vh "github.com/Tryanks/virtualhere-go"
)

func main() {
    // Create client with service management
    client, err := vh.NewClient("/path/to/vhclient",
        vh.WithService(true),
        vh.WithOnProcessTerminated(func() {
            fmt.Println("VirtualHere client terminated!")
        }),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close() // Gracefully shutdown the service

    // Now use the client...
    state, err := client.List()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Found %d hubs\n", len(state.Hubs))
}

More Examples

// Add a manual hub
client.ManualHubAdd("192.168.1.100:7575")

// Enable auto-use for all devices on a hub
client.AutoUseHub("raspberrypi:7575")

// Get device information
info, err := client.DeviceInfo("raspberrypi.114")
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Vendor: %s\nProduct: %s\n", info.Vendor, info.Product)

// Get detailed client state as XML
xmlState, err := client.GetClientState()
if err != nil {
    log.Fatal(err)
}

How It Works

This library communicates with the VirtualHere client daemon using platform-specific IPC:

Windows

Uses Windows Named Pipe at \\.\pipe\vhclient. The library opens the pipe, writes the command, and reads the response in message mode.

Linux/macOS

Uses two Unix domain sockets:

  • /tmp/vhclient - for sending commands (write only)
  • /tmp/vhclient_response - for receiving responses (read only)

The command must be terminated with a newline character (\n).

API Documentation

See the GoDoc for full API documentation.

License

MIT License - see LICENSE file for details.

Author

Tryanks (tryanks@outlook.com)

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages