gogige

package module
v1.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2026 License: BSD-3-Clause Imports: 14 Imported by: 0

README

gogige

Pure-Go GigE Vision client (package gige) for Huaray/Dahua 3D volume cameras.

Go Version License Release Pure Go

Tested on:

Manufacturer Model Description
Huaray Technology (iRAYPLE) DS5131MG30CE 3D stereo industrial smart camera for machine vision, industrial automation, and precise depth measurement.

Table of Contents

Features

  • GigE Vision control — GVCP register read/write, heartbeat maintenance, and access-privilege management over a dedicated control channel.
  • Streaming — GVSP receiver with pre-allocated buffer pool, packet resend, and multi-part/GenDC payload parsing.
  • GenICam GenApi XML — Fetch, decompress, and build the camera node map (IntReg, Enumeration, SwissKnife, Converter, Port, …).
  • 3D volume (BSCF) — Per-frame color/depth/mono components with JPEG encoding and mm-scale measurements (WidthMm, HeightMm, Length, PackCount).
  • Live preview — App-owned sinks (live.NewLive), switch components mid-stream.
  • Zero-alloc hot pathgvsp.Receiver allocates nothing per packet during streaming.

Getting Started

Prerequisites
  • Go 1.23+
  • A GigE Vision camera on the same L2 network (a simulator works for control-plane work)
  • Optional: Jumbo-frames-capable NIC for high-throughput streaming
Installation
go get github.com/aaronmurniadi/gogige
Quick start

Open a camera, configure a feature, and grab a frame. There are two handles that share one feature vocabulary (SetInteger/SetEnum/SetBoolean/SetFloat/SetString plus matching getters):

  • gogige.OpenDevice*Camera: control + live frames + one-shot samples.
  • gogige.OpenDevice: control (dev.Features()) + StartGrabber/Grabber.

One-shot sample straight from the Camera:

cam, err := gige.OpenDevice(ctx, "192.168.1.10",
    gige.WithLogger(logger),
    gige.WithTimeout(2*time.Second),
)
defer cam.Close()
_ = cam.SetEnum("PixelFormat", "Mono8")

sample, err := cam.GrabSample(ctx, gige.ComponentDepth) // Sample: JPEG + LengthMm/WidthMm/HeightMm/PackCount/Packs

Continuous frames:

stream, err := cam.StartStream(ctx)
defer stream.Stop()
for frame := range stream.Frames() {
    // use frame.Data
    frame.Release() // return to the buffer pool
}

Usage

One-shot grab (fully automated open→grab→close):

jpeg, err := gogige/grab.GrabJPEG(ctx, "192.168.1.10")
// or from a Camera you already hold:
jpeg, err := gogige/grab.FromCamera(ctx, cam, gogige.ComponentColor)

Discover cameras:

devs, err := gige.Discover(ctx, 2*time.Second)

Live preview (app owns the sink):

l := gogige/live.NewLive(dev, gogige/live.WithSink(gogige.JPEGFunc(hub.Broadcast)), gogige/live.WithLiveComponent(gogige.ComponentDepth))
l.Start(ctx)
defer l.Stop()
sample := l.LatestSample() // filter/validate in the app
// l.SetComponent(gogige.ComponentColor) // switch mid-stream

Logging: gogige.WithLogger(...) accepts any Logger implementation (e.g. gogige.Slog(slog.Default()) or your own wrapper around zerolog/zap). Default is a no-op.

Project Structure

gogige/
├── cmd/
│   ├── gogige-discover/      # CLI discovery utility
│   └── gogige-stream/        # CLI stream capture utility
├── camera.go                 # Camera, feature get/set, one-shot grabs
├── device.go                 # Device (Open), OpenDevice, Features impl
├── stream.go                 # Session/Grabber, StartStream + Stream.Frames()
├── options.go                # WithLogger/WithTimeout/WithComponent, const Version
├── interfaces.go             # Device, Features, Grabber, FrameSink, JPEGFunc
├── alias.go                  # gogige.Sample/Frame/GVCP/… re-exports
├── discovery.go              # Discover → DeviceInfo
├── log.go                    # Logger, NopLogger, Slog
├── genapi/                   # GenICam GenApi XML parser / node map
├── gvcp/                     # GigE Vision Control Protocol
├── gvsp/                     # GigE Vision Streaming Protocol
├── gentl/                    # GenTL constants (no CGO)
├── internal/                 # color (PFNC decode + JPEG), genDC
├── grab/                     # One-shot GrabJPEG / FromCamera
├── live/                     # Continuous preview loop
├── examples/                 # Runnable examples (smoke-test, grab, live, …)
├── .githooks/                # Versioned git hooks (gofmt + go test)
├── AGENTS.md                 # Project & protocol rules
├── CHANGELOG.md
├── ROADMAP.md
├── go.mod
└── LICENSE

Examples

Omit -ip to pick the first camera from GigE discovery (or pass -ip explicitly).

Pre-commit

Once per clone, point git at the versioned hooks (runs gofmt on staged .go files, then go test ./...):

git config core.hooksPath .githooks

Contributing

Contributions are welcome! Feel free to open an issue or submit a pull request following these simple steps:

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

Distributed under the BSD 3-Clause License. See LICENSE for more information.

Documentation

Overview

Package gogige is a pure-Go GigE Vision client.

Controlled access: OpenDevice returns a *Camera. Use Camera.SetInteger / SetEnum / SetFloat / SetBoolean / SetString to write features and their matching getter (Integer / Enum / Float / Boolean / String) to read them.

cam, err := gogige.OpenDevice(ctx, "192.168.1.10")
defer cam.Close()
_ = cam.SetInteger("Width", 1920)
_ = cam.SetEnum("PixelFormat", "Mono8")
_ = cam.SetBoolean("AcquisitionStart", true)

Live frames (Phase 4): Camera.StartStream → stream.Frames() of pooled frames; Release() each frame back to the buffer pool.

stream, err := cam.StartStream(ctx)
defer stream.Stop()
for frame := range stream.Frames() {
	// use frame.Data
	frame.Release()
}

One-shot samples (Huaray BSCF): Camera.GrabSample / GrabAllSamples / GrabJPEG grab a single frame directly from the Camera. For continuous preview use a Device (Open → StartGrabber → Grabber.Grab) or live.NewLive.

dev, _ := gogige.Open(ctx, ip) g, _ := dev.StartGrabber(ctx) sample, _ := g.Grab(ctx) // sample.JPEG + mm measurements

Protocol packages:

  • gvcp — GigE Vision Control Protocol (GenCP)
  • genapi — GenICam GenApi XML / node map
  • gvsp — GigE Vision Streaming Protocol
  • gentl — GenTL constants (no CGO)

References

Index

Constants

View Source
const (
	ComponentUnknown = gvsp.ComponentUnknown
	ComponentMono    = gvsp.ComponentMono
	ComponentDepth   = gvsp.ComponentDepth
	ComponentColor   = gvsp.ComponentColor
)

SFNC-style imaging components (BSCF ImageType wire values).

View Source
const Version = "1.5.0"

Version is the library version.

Variables

View Source
var (
	DialGVCP                = gvcp.DialGVCP
	ParseNodeMap            = genapi.ParseNodeMap
	FetchXML                = genapi.FetchXML
	ListenStream            = gvsp.ListenStream
	SampleFromBSCF          = gvsp.SampleFromBSCF
	SampleFromBSCFComponent = gvsp.SampleFromBSCFComponent
	SampleAllFromBSCF       = gvsp.SampleAllFromBSCF
	ParseBSCF               = gvsp.ParseBSCF
	ParseComponent          = gvsp.ParseComponent
	IsBSCF                  = gvsp.IsBSCF
	EncodeJPEG              = color.EncodeJPEG
	StartAcquisition        = gvcp.StartAcquisition
	StopAcquisition         = gvcp.StopAcquisition
)

Re-exports of common constructors / parsers.

Functions

func ApplyControlPair

func ApplyControlPair(c *Camera, pair string) error

ApplyControlPair sets one GenICam feature from "Name=value" string.

Types

type Camera

type Camera struct {
	IP string
	// contains filtered or unexported fields
}

Camera is a connected GigE Vision device with GenICam feature access.

func Connect

func Connect(ip string) (*Camera, error)

Connect opens GVCP to the camera at ip, takes control, and loads GenICam XML.

func New

func New(ip string, g *gvcp.GVCP, nodes *genapi.NodeMap, log Logger) *Camera

New builds a Camera from an already-connected GVCP client and NodeMap.

func OpenDevice added in v0.9.0

func OpenDevice(ctx context.Context, ip string, opts ...Option) (*Camera, error)

OpenDevice connects to a GigE Vision camera and returns the Camera directly (Phase 4 surface). Use Camera.SetInteger / SetEnum for control and Camera.StartStream for live frames.

func (*Camera) Boolean added in v1.5.0

func (c *Camera) Boolean(name string) (bool, error)

Boolean reads the current value of a boolean GenICam feature.

func (*Camera) BooleanFeature added in v0.7.0

func (c *Camera) BooleanFeature(name string) (bool, error)

BooleanFeature reads a boolean GenICam feature (alias for Boolean).

func (*Camera) Close

func (c *Camera) Close()

Close releases control and the GVCP socket.

func (*Camera) Enum added in v1.5.0

func (c *Camera) Enum(name string) (string, error)

Enum reads the current enumeration symbol of an enumeration GenICam feature.

func (*Camera) Execute

func (c *Camera) Execute(name string) error

Execute implements gvcp.Commander.

func (*Camera) ExecuteCommand

func (c *Camera) ExecuteCommand(name string) error

ExecuteCommand executes a GenICam command node.

func (*Camera) Features added in v1.5.0

func (c *Camera) Features() Features

Features returns a Features view backed by this Camera, so callers that already hold a *Camera can use the same feature accessors as a Device.

func (*Camera) Float added in v1.5.0

func (c *Camera) Float(name string) (float64, error)

Float reads the current value of a float GenICam feature.

func (*Camera) GVCP

func (c *Camera) GVCP() *gvcp.GVCP

GVCP returns the underlying control client.

func (*Camera) GrabAllSamples added in v1.5.0

func (c *Camera) GrabAllSamples(ctx context.Context) ([]Sample, error)

GrabAllSamples opens a transient GVSP stream on the camera, picks one frame, and returns a Sample for every BSCF component (color, depth, mono, …).

func (*Camera) GrabComponents added in v1.5.0

func (c *Camera) GrabComponents(ctx context.Context) ([]Sample, error)

GrabComponents opens a transient GVSP stream on the camera and returns one frame's BSCF components without JPEG encoding (raw Data, dimensions, pixel format).

func (*Camera) GrabJPEG added in v1.5.0

func (c *Camera) GrabJPEG(ctx context.Context, comp Component) ([]byte, error)

GrabJPEG opens a transient GVSP stream on the camera, picks one frame, and returns the JPEG bytes for the requested component (default color).

func (*Camera) GrabSample added in v1.5.0

func (c *Camera) GrabSample(ctx context.Context, comp Component) (Sample, error)

GrabSample opens a transient GVSP stream on the camera, picks one frame, and returns it as a Sample with a JPEG for the requested component. comp of ComponentUnknown selects ComponentColor. Closes the stream before returning. Prefer StartStream for continuous capture; this is for one-off grabs from a Camera you already hold.

func (*Camera) Has

func (c *Camera) Has(name string) bool

Has reports whether a GenICam feature exists (gvcp.Commander).

func (*Camera) Integer added in v1.5.0

func (c *Camera) Integer(name string) (int64, error)

Integer reads the current value of an integer GenICam feature.

func (*Camera) Logger added in v0.2.0

func (c *Camera) Logger() Logger

Logger returns the camera logger (never nil).

func (*Camera) NodeMap

func (c *Camera) NodeMap() *genapi.NodeMap

NodeMap returns the loaded GenICam map.

func (*Camera) SetBoolean added in v1.5.0

func (c *Camera) SetBoolean(name string, v bool) error

SetBoolean sets a boolean GenICam feature.

func (*Camera) SetBooleanFeature

func (c *Camera) SetBooleanFeature(name string, v bool) error

SetBooleanFeature sets a boolean GenICam feature (alias for SetBoolean).

func (*Camera) SetEnum added in v0.9.0

func (c *Camera) SetEnum(name, value string) error

SetEnum sets an enumeration GenICam feature.

func (*Camera) SetFloat added in v1.5.0

func (c *Camera) SetFloat(name string, v float64) error

SetFloat sets a float GenICam feature.

func (*Camera) SetFloatFeature

func (c *Camera) SetFloatFeature(name string, v float64) error

SetFloatFeature sets a float GenICam feature (alias for SetFloat).

func (*Camera) SetIntFeature

func (c *Camera) SetIntFeature(name string, v int64) error

SetIntFeature sets an integer GenICam feature (alias for SetInteger).

func (*Camera) SetInteger added in v0.9.0

func (c *Camera) SetInteger(name string, v int64) error

SetInteger sets an integer GenICam feature.

func (*Camera) SetString added in v1.5.0

func (c *Camera) SetString(name, v string) error

SetString sets a string or enumeration GenICam feature.

func (*Camera) SetStringFeature

func (c *Camera) SetStringFeature(name, v string) error

SetStringFeature sets a string or enumeration GenICam feature (alias for SetString/SetEnum).

func (*Camera) StartStream added in v0.9.0

func (c *Camera) StartStream(ctx context.Context) (*Stream, error)

StartStream opens a GVSP channel on c and begins acquisition. Frames are delivered over Stream.Frames() until the context is cancelled or Stop is called. The Camera stays open; close it separately when done.

func (*Camera) String added in v1.5.0

func (c *Camera) String(name string) (string, error)

String reads the current string value of a string GenICam feature.

type Component added in v0.5.0

type Component = gvsp.Component

Type aliases keep the root consumer API ergonomic for protocol types.

type Device

type Device interface {
	IP() string
	Features() Features
	StartGrabber(ctx context.Context, opts ...GrabOption) (Grabber, error)
	Close() error
}

Device is a connected camera handle (control + ability to start streaming).

func Open

func Open(ctx context.Context, ip string, opts ...Option) (Device, error)

Open connects to a GigE Vision camera and returns a Device.

type DeviceInfo

type DeviceInfo struct {
	IP           string
	MAC          string
	Manufacturer string
	Model        string
	Serial       string
	UserName     string
}

DeviceInfo is a camera found via GigE Vision discovery (root API).

func Discover

func Discover(ctx context.Context, timeout time.Duration) ([]DeviceInfo, error)

Discover broadcasts a GigE Vision DISCOVERY_CMD and collects acknowledgements. timeout bounds how long to wait for replies after the broadcast.

type Features

type Features interface {
	SetBool(name string, v bool) error
	Bool(name string) (bool, error)
	SetInt(name string, v int64) error
	Int(name string) (int64, error)
	SetFloat(name string, v float64) error
	Float(name string) (float64, error)
	SetString(name, v string) error
	String(name string) (string, error)
	Enum(name string) (string, error)
	Execute(name string) error
	Has(name string) bool
}

Features is GenICam feature access without exposing NodeMap. It mirrors the short forms on Camera (SetInteger/Integer, SetEnum/Enum, …) so a Device and a Camera share one consistent vocabulary.

type Frame

type Frame = gvsp.Frame

Type aliases keep the root consumer API ergonomic for protocol types.

type FrameSink

type FrameSink interface {
	SendJPEG(jpeg []byte)
}

FrameSink receives JPEG frames from Live for preview (WebSocket, MJPEG, etc.). Implement this in application code — the library does not ship a WebSocket server. Flow control is optional: implement Throttler separately if the sink supports it.

type GVCP

type GVCP = gvcp.GVCP

Type aliases keep the root consumer API ergonomic for protocol types.

type GVSPStream added in v0.9.0

type GVSPStream = gvsp.Stream

Type aliases keep the root consumer API ergonomic for protocol types.

type GrabOption added in v0.4.0

type GrabOption func(*Session)

GrabOption configures StartGrabber / Session.

func GrabComponent added in v0.5.0

func GrabComponent(comp Component) GrabOption

GrabComponent selects which BSCF/SFNC component Session.Grab decodes.

type Grabber

type Grabber interface {
	Grab(ctx context.Context) (Sample, error)
	GrabAll(ctx context.Context) ([]Sample, error)
	SetComponent(Component)
	Pause(ctx context.Context) error
	Resume(ctx context.Context) error
	Close() error
}

Grabber is a live GVSP acquisition stream.

type JPEGFunc

type JPEGFunc func([]byte)

JPEGFunc adapts a callback into a FrameSink. It is stateless and therefore does not implement Throttler. Handy for wiring live to an existing broadcast function:

l := live.NewLive(dev, live.WithSink(JPEGFunc(hub.Broadcast)))

func (JPEGFunc) SendJPEG

func (f JPEGFunc) SendJPEG(jpeg []byte)

type Logger

type Logger interface {
	Debug(msg string, kv ...any)
	Info(msg string, kv ...any)
	Warn(msg string, kv ...any)
	Error(msg string, kv ...any)
}

Logger is a minimal structured logger. Default is a no-op.

func Slog added in v0.8.0

func Slog(z *slog.Logger) Logger

Slog wraps a log/slog.Logger as a Logger. Pass slog.Default() or any handler:

gogige.Open(ctx, ip, gogige.WithLogger(gogige.Slog(slog.Default())))

type NodeMap

type NodeMap = genapi.NodeMap

Type aliases keep the root consumer API ergonomic for protocol types.

type NopLogger

type NopLogger struct{}

NopLogger discards all log events.

func (NopLogger) Debug

func (NopLogger) Debug(string, ...any)

func (NopLogger) Error

func (NopLogger) Error(string, ...any)

func (NopLogger) Info

func (NopLogger) Info(string, ...any)

func (NopLogger) Warn

func (NopLogger) Warn(string, ...any)

type Option

type Option func(*openConfig)

Option configures Open / device connection.

func WithComponent added in v0.5.0

func WithComponent(comp Component) Option

WithComponent selects which BSCF/SFNC component GrabJPEG uses (color/depth/mono). Default: ComponentColor.

func WithLogger

func WithLogger(l Logger) Option

WithLogger sets the logger used by this device (default: NopLogger).

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout sets the GVCP dial / control timeout (default: 2s).

type Port

type Port = gvcp.Port

Type aliases keep the root consumer API ergonomic for protocol types.

type Sample

type Sample = gvsp.Sample

Type aliases keep the root consumer API ergonomic for protocol types.

type Session

type Session struct {
	// contains filtered or unexported fields
}

Session is a persistent GVSP stream session. It implements Grabber.

func NewFromCamera

func NewFromCamera(cam *Camera) *Session

NewFromCamera returns a Session that streams using cam without taking ownership.

func NewSession

func NewSession() *Session

NewSession returns an empty GVSP session (Connects on Open if no camera set).

func (*Session) Close

func (s *Session) Close() error

Close stops acquisition and releases stream resources. The Camera is closed only when the Session owns it (not when Device owns it).

func (*Session) Grab

func (s *Session) Grab(ctx context.Context) (Sample, error)

Grab implements Grabber: receives one GVSP frame, parses BSCF, returns JPEG Sample.

func (*Session) GrabAll added in v0.4.0

func (s *Session) GrabAll(ctx context.Context) ([]Sample, error)

GrabAll receives one GVSP frame and returns a JPEG Sample for every BSCF component (color, depth, mono, …). Non-BSCF payloads yield a single sample.

func (*Session) GrabComponents added in v0.7.0

func (s *Session) GrabComponents(ctx context.Context) ([]Sample, error)

GrabComponents receives one GVSP frame and returns its BSCF components without JPEG encoding (raw Data, dimensions, pixel format). Non-BSCF payloads yield a single Sample with ComponentUnknown and no JPEG. Useful to probe what a camera is actually streaming beyond the JPEG color path.

func (*Session) Open

func (s *Session) Open(ip string) error

Open connects (if needed), starts GVSP, and begins acquisition.

func (*Session) Opened

func (s *Session) Opened() bool

Opened reports whether the session is open.

func (*Session) Pause

func (s *Session) Pause(ctx context.Context) error

Pause implements Grabber.

func (*Session) PauseStreaming

func (s *Session) PauseStreaming() error

PauseStreaming stops image transfer but keeps CCP, heartbeat, and GVSP socket.

func (*Session) Resume

func (s *Session) Resume(ctx context.Context) error

Resume implements Grabber.

func (*Session) ResumeStreaming

func (s *Session) ResumeStreaming() error

ResumeStreaming re-programs the stream channel and starts acquisition again.

func (*Session) SetComponent added in v0.5.0

func (s *Session) SetComponent(c Component)

SetComponent selects which BSCF/SFNC component Grab returns (color/depth/mono).

type Stream

type Stream struct {
	// contains filtered or unexported fields
}

Stream is a live GVSP acquisition channel (Phase 4). Create one via Camera.StartStream, consume pooled frames from Frames(), and Release() each frame back to the pre-allocated buffer pool.

func (*Stream) Frames added in v0.9.0

func (st *Stream) Frames() <-chan *Frame

Frames returns the channel of pooled frames. The channel closes when the stream ends (context cancelled, Stop called, or the session goes away).

func (*Stream) Pause added in v0.9.0

func (st *Stream) Pause() error

Pause stops image transfer but keeps the control channel and socket open.

func (*Stream) Resume added in v0.9.0

func (st *Stream) Resume() error

Resume re-programs the stream channel and restarts acquisition.

func (*Stream) Stop added in v0.9.0

func (st *Stream) Stop()

Stop ends acquisition, closes the stream socket, and stops the background goroutine. Safe to call more than once.

type Throttler added in v1.5.0

type Throttler interface {
	Throttle()
	Unthrottle()
}

Throttler is optional flow control for a FrameSink. Live asserts this and calls Throttle/Unthrottle only when the sink opts in, so simple stateless sinks (e.g. JPEGFunc) need no stub methods. Unlike Grabber.Pause/Resume (which throttle camera acquisition), this throttles delivery to the consumer.

Directories

Path Synopsis
Package calib converts between camera-frame 3D coordinates (millimetres) and image pixel coordinates using pinhole intrinsics.
Package calib converts between camera-frame 3D coordinates (millimetres) and image pixel coordinates using pinhole intrinsics.
cmd
gogige-discover command
gogige-discover broadcasts GigE Vision DISCOVERY_CMD and prints peers.
gogige-discover broadcasts GigE Vision DISCOVERY_CMD and prints peers.
gogige-stream command
gogige-stream captures N frames (JPEG + BSCF measurements) from a GigE camera.
gogige-stream captures N frames (JPEG + BSCF measurements) from a GigE camera.
Package genapi provides GenICam GenApi XML parser and node map implementation.
Package genapi provides GenICam GenApi XML parser and node map implementation.
Package gentl provides GenTL (GenICam Transport Layer) definitions.
Package gentl provides GenTL (GenICam Transport Layer) definitions.
Package gvcp provides GigE Vision Control Protocol (GVCP) implementation.
Package gvcp provides GigE Vision Control Protocol (GVCP) implementation.
Package gvsp provides GigE Vision Streaming Protocol (GVSP) implementation.
Package gvsp provides GigE Vision Streaming Protocol (GVSP) implementation.
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL