eev

package module
v0.0.12 Latest Latest
Warning

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

Go to latest
Published: Apr 30, 2026 License: MIT Imports: 19 Imported by: 1

README

goEEVideo – Go Client Library for Embedded Ethernet Video (EEV) Devices

Go Reference

goEEVideo is a Go client library for discovering, configuring, and controlling Embedded Ethernet Video (EEV) devices over UDP/CoAP.

It enables:

  • Network discovery of EEV-compatible hardware
  • Generation of device configuration YAML files
  • High-level API register read/write access by name
  • Low-level API register read/write access by address
  • Register field-level configuration
  • String register handling

Ideal for machine vision cameras, embedded video encoders, industrial imaging devices, or any hardware implementing the EEV protocol.

Features

  • UDP CoAP multicast discovery
  • CoAP client tailored for EEV register access (custom options 65301 & 65305)
  • Symbolic register names from device YAML → easier & safer usage
  • Individual register field writes using the WriteRegFields function
  • Configurable UDP source port and CoAP token length
  • Verbose logging support
  • MIT licensed

Installation

go get gitlab.com/eevideo/goeevideo@latest

Quick Start

1. Discover Devices
Example
import (
	"fmt"
	"os"

	"gitlab.com/eevideo/goeevideo"
)

func main() {
	// "Unknown nic" scans all interfaces; otherwise use OS network interface name
	// e.g. "eth0", "Ethernet", etc.
	deviceCfg, err := eev.DiscDevices("Unknown nic", 2000) // timeout in milliseconds, 3 sec
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error EEV Discovery: %v\n", err)
		os.Exit(1)
	}
	fmt.Println("Discovery complete")
}

This facilitate creation of files like "./deviceCfgs/device-.yaml" which store device information such as capabilities, network info, and a register map.

2. Interface with an EEV Device
Examples
import (
	"fmt"
	"os"

	"gitlab.com/eevideo/goeevideo"
)

err := eev.Init(./deviceCfgs/Your_Device.yaml) // Replace with config file path/name
if err != nil {
	fmt.Fprintf(os.Stderr, "Error EEV Init: %v\n", err)
	os.Exit(1)
}

// ── High-level: Name based ──
// Read
regName := "eth0_IPAddress"  // Replace with an actual register name in config file
rdData, fields, err := eev.Device.ReadReg(regName)
if err != nil {
	fmt.Fprintf(os.Stderr, "Error EEV ReadReg: %v\n", err)
	os.Exit(1)
}
fmt.Printf("Register %16s = 0x%X\n", regName, rdData)
fmt.Println("Fields:")
for fieldName, fieldValue := range fields {
	fmt.Printf("%8s: 0x%X\n", fieldName, fieldValue)
}

// Write
regName = "stream0_DestPort"
uVal := uint32(55550)
err = eev.Device.WriteReg(regName, uVal)
if err != nil {
	fmt.Fprintf(os.Stderr, "Error EEV WriteReg: %v\n", err)
	os.Exit(1)
}
fmt.Printf("Wrote register %s to 0x%x\n", regName, uVal)

// Field-level Write
regName = "stream0_DestPort"
destPort := map[string]uint32{"dport": 55550,}
err = eev.Device.WriteRegFields(regName, destPort)
if err != nil {
	fmt.Fprintf(os.Stderr, "Error EEV WriteRegFields: %v\n", err)
	os.Exit(1)
}
fmt.Printf("Wrote register %s fields\n", regName)


// ── Low-level: Address based ──
// Read
uAddr := uint32(0x40224)
rdData, err := eev.Device.RegReadU32(uAddr)
if err != nil {
	fmt.Fprintf(os.Stderr, "Error EEV RegReadU32: %v\n", err)
	os.Exit(1)
}
fmt.Printf("Read register 0x%x returned 0x%x\n", uAddr, rdData)

// Write
uAddr = uint32(0x40224)
uVal = uint32(55550)
err = eev.Device.RegWriteU32(uAddr, uVal)
if err != nil {
	fmt.Fprintf(os.Stderr, "Error EEV RegWriteU32: %v", err)
	os.Exit(1)
}
fmt.Printf("Wrote register 0x%x to 0x%x\n", uAddr, uVal)
Global Configuration (optional)
eev.SetEevReqUdpPort(54321)   // Custom client UDP source port (0 = auto)
eev.SetTokenLen(4)            // CoAP token length
eev.Verbose = 1               // 0 = silent, 1–3 = increasing debug output

Typical Workflow

Call eev.DiscDevices(...) → creates YAML configs
Initialize: eev.Init(...) (sets up global eev.Device)
Use eev.Device.ReadReg(...), eev.Device.WriteReg(...), etc.
For direct/low-level needs → eev.Device.RegReadU32(...), eev.Device.RegReadU32(...), etc.

Requirements

Go ≥ 1.18
UDP access to devices (default port 5683)
Devices must support EEV discovery and CoAP register protocol

Authors and Acknowledgment

Tecphos

License

See LICENSE file.


Documentation

Index

Constants

View Source
const (
	PacketTypeLeader  = 0x1
	PacketTypePayload = 0x3
	PacketTypeTrailer = 0x2
)

Packet Types as defined in GVSP Protocol

View Source
const (
	GvspImage = 1
	GvspJPEG  = 6
)

Payload Types

View Source
const (
	MONO8         = 0x01080001
	MONO16        = 0x01100007
	GR8           = 0x01080008
	RG8           = 0x01080009
	GB8           = 0x0108000A
	BG8           = 0x0108000B
	RGB8          = 0x02180014
	YUV422_8_UYVY = 0x0210001F
)

Supported Pixel Formats

View Source
const (
	OptionEevRegAccess     uint16 = 65301
	OptionEevBinaryAddress uint16 = 65305
)
View Source
const (
	EevUdpPort int = 5683
	EevTimeOut     = 1000 * time.Millisecond
)
View Source
const (
	// SPI CTRL Register bitfields
	SPI_CTRL_EN uint8 = 0 // (r/w): SPI unit enable

	// SPI_CTRL_RX_AVAIL   uint8 = 16 // (r/-): RX FIFO data available (RX FIFO not empty)
	// SPI_CTRL_TX_EMPTY   uint8 = 17 // (r/-): TX FIFO empty
	SPI_CTRL_TX_FULL uint8 = 18 // (r/-): TX FIFO full

	// SPI_CTRL_CS_ACTIVE  uint8 = 30 // (r/-): At least one CS line is active when set
	SPI_CTRL_BUSY uint8 = 31 // (r/-): SPI busy or TX FIFO not empty yet (read-only)

	// SPI DATA Register bitfields
	// SPI_DATA_LSB        uint8 =  0 // (r/w): Data byte LSB
	SPI_DATA_CSEN uint8 = 3 // (-/w): Chip select enable (command-mode)
	// SPI_DATA_MSB        uint8 =  7 // (r/w): Data byte MSB
	SPI_DATA_CMD uint8 = 31 // (-/w): 1=command, 0=data

	// SPI Flash Commands
	SPI_PAGE_PROG uint8 = 0x02
	SPI_READ      uint8 = 0x03
	// SPI_WRITE_DIS       uint8 = 0x04
	SPI_READ_STATUS uint8 = 0x05
	SPI_WRITE_EN    uint8 = 0x06

	SPI_4KB_ERASE  uint8 = 0x20
	SPI_32KB_ERASE uint8 = 0x52
	SPI_64KB_ERASE uint8 = 0xD8

	SPI_RDID uint8 = 0x9F

	// SPI flash Status Register bitfields
	SPI_SREG_BUSY uint8 = 0 // Busy, write/erase in progress when set, read-only

	// UDP packet related parameters
	SPI_RETRIES      int           = 20   // Register Read/Write retries
	SPI_SLEEP        time.Duration = 100  // Register Read/Write retry delay in Milliseconds
	SPI_PAYLOAD_SIZE uint32        = 1450 // Max UDP payload size, standard MTU 1500-headers
)

Variables

View Source
var (
	Device        *DeviceType
	EevTokenLen   uint8
	EevReqUdpPort int
	Verbose       int
	HostUDP       *net.UDPAddr
	DeviceUDP     *net.UDPAddr
)
View Source
var CoapRespCodes = map[uint8]CoapRespCode{
	64: {"2.00 Success"},

	68:  {"2.04 Changed"},
	69:  {"2.05 Content"},
	128: {"4.00 Bad Request"},
	129: {"4.01 Unauthorized"},
	130: {"4.02 Bad Option"},
	131: {"4.03 Forbidden"},
	132: {"4.04 Not Found"},

	160: {"5.00 Internal Server Error"},
	161: {"5.01 Not Implemented"},
}

CoAP Message Response Codes (combined Class and Detail fields, c.dd)

View Source
var REGADDR_SPI_CTRL uint32 = 0x380000

SPI Peripheral Register Address

View Source
var REGADDR_SPI_DATA uint32 = 0x380004
View Source
var YamlFiles embed.FS

Functions

func CheckDir added in v0.0.7

func CheckDir(outputDir string) error

CheckDir checks if the provided file path directory exists, creates it if not, and also checks if it is writable

func FrameCapture added in v0.0.10

func FrameCapture(ctx context.Context, conn *net.UDPConn, maxPkt uint16,
	timeout time.Duration, dataCh chan<- *ImageBuffer) struct {
	Wg    *sync.WaitGroup
	ErrCh chan error
}

FrameCapture runs the frame collection go routine. Returns WaitGroup and an error channel (receives first fatal error or nil on clean exit).

func GvspFrame added in v0.0.7

func GvspFrame(ctx context.Context, conn *net.UDPConn, udpPktBuffer []byte,
	timeout time.Duration, dataCh chan<- *ImageBuffer) error

GvspFrame collects one complete frame and sends it to dataCh when complete. Returns nil on success (frame sent), or error on fatal issues. Non-fatal packet errors can be printed.

func Init

func Init(deviceFile string) error

Init initailizes an EEV DeviceType structure

func PixelFormatFromString added in v0.0.7

func PixelFormatFromString(pixFmt string) (uint32, error)

PixelFormatFromString converts a pixel format string to the corresponding pixel format constant. If the string is empty or unsupported, return an error.

func ReadI2c added in v0.0.6

func ReadI2c(port string, i2cID uint32, rdLen int) ([]byte, error)

func ReadI2cAddr added in v0.0.8

func ReadI2cAddr(port string, i2cID uint32, addrBytes []byte, rdLen int) ([]byte, error)

func SPIeraseBlocks added in v0.0.12

func SPIeraseBlocks(fileBytes int, chipSel uint8, addrSize uint8, startAddr uint32) error

Erase 64KB blocks for the provided amount of fileBytes beginning at startAddr

func SPIsetRegAddrCtrl added in v0.0.12

func SPIsetRegAddrCtrl(addr uint32)

Change SPI Peripheral Ctrl Register Address

func SPIsetRegAddrData added in v0.0.12

func SPIsetRegAddrData(addr uint32)

Change SPI Peripheral Data Register Address

func SPIwriteFile added in v0.0.12

func SPIwriteFile(f *os.File, fileBytes int, chipSel uint8, addrSize uint8, startAddr uint32) error

SPIwriteFile writes the provided binary file of given fileBytes size to SPI flash, managing page boundaries and performing verification.

func SetEevReqUdpPort added in v0.0.2

func SetEevReqUdpPort(port uint16)

Sets the client side UDP port used for EEVideo commands (Default is 0 for random OS assigned Source Port). Typically set to a value in the Dynamic/Private Ports range (49152 - 65535)

func SetTokenLen

func SetTokenLen(tokenLen uint8) error

Sets the Token Length for EEVideo commands. Default is 1.

func SetupStreamListener added in v0.0.8

func SetupStreamListener(streamDestIP string, streamDestPort uint16, hostIP string) (*net.UDPConn, error)

SetupStreamListener creates a UDP listener for either multicast or unicast and joins the multicast group if needed.

func WriteI2C added in v0.0.6

func WriteI2C(port string, i2cID uint32, addrBytes []byte, dataBytes []byte) error

Types

type CapabilitiesType added in v0.0.2

type CapabilitiesType struct {
	DecAvail  bool `yaml:"decAvail"`
	MultAddr  bool `yaml:"multAddr"`
	StringRd  bool `yaml:"stringRd"`
	FifoRd    bool `yaml:"fifoRd"`
	ReadRst   bool `yaml:"readRst"`
	MaskWr    bool `yaml:"maskWr"`
	BitTog    bool `yaml:"bitTog"`
	BitSet    bool `yaml:"bitSet"`
	BitClear  bool `yaml:"bitClear"`
	StaticIP  bool `yaml:"staticIP"`
	LinkLocIP bool `yaml:"linkLocIP"`
	DhcpIP    bool `yaml:"dhcpIP"`
	MultiDisc bool `yaml:"multiDisc"`
}

type CoAPMessage

type CoAPMessage struct {
	Version   uint8
	Type      uint8
	TokenLen  uint8
	Code      uint8
	MessageID uint16
	Token     []byte
	Options   []CoAPOption
	Payload   []byte
}

CoAPMessage represents a parsed CoAP message

type CoAPOption

type CoAPOption struct {
	Number uint16
	Length uint16
	Value  []byte
}

CoAPOption represents a single CoAP option

type CoapRespCode

type CoapRespCode struct {
	Desc string
}

CoapRespCode represents the value(s) in one CoapRespCode key

type DeviceMapType added in v0.0.2

type DeviceMapType struct {
	LastStatic   uint32 `yaml:"lastStatic"`
	FirstMutable uint32 `yaml:"firstMutable"`
	LastMutable  uint32 `yaml:"lastMutable"`
}

type DeviceRegisterAddrType added in v0.0.2

type DeviceRegisterAddrType struct {
	Addr     uint32               `yaml:"addr"`
	Access   string               `yaml:"acc"`
	IntValue uint32               `yaml:"intval"`
	StrValue string               `yaml:"strval"`
	Fields   map[string]FieldType `yaml:"fields,omitempty"`
}

type DeviceRegisterType added in v0.0.2

type DeviceRegisterType struct {
	Addr     uint32               `yaml:"addr"`
	Name     string               `yaml:"name"`
	Access   string               `yaml:"acc"`
	IntValue uint64               `yaml:"intval"`
	StrValue string               `yaml:"strval"`
	Fields   map[string]FieldType `yaml:"fields,omitempty"`
}

type DeviceType added in v0.0.2

type DeviceType struct {
	Location     LocationType                      `yaml:"location"`
	Capabilities CapabilitiesType                  `yaml:"capabilities"`
	Map          DeviceMapType                     `yaml:"map"`
	Registers    map[string]DeviceRegisterAddrType `yaml:"features"`
}

func DiscDevices added in v0.0.2

func DiscDevices(discNicName string, udpTimeout int) ([]DeviceType, error)

Top level function call for Discovering EEVideo Devices

func ReadDeviceYAML added in v0.0.10

func ReadDeviceYAML(file_loc string) (*DeviceType, error)

ReadDeviceYAML unmarshals/reads an EEVideo device YAML file

func (*DeviceType) ReadReg added in v0.0.4

func (Device *DeviceType) ReadReg(regName string) (uint32, map[string]uint32, error)

ReadReg uses a register name string to read a register containing a uint32 value. It returns the uint32 value and a map of field and value pairs.

func (*DeviceType) ReadRegString added in v0.0.4

func (Device *DeviceType) ReadRegString(regName string) (string, error)

ReadRegString is used to read a register containing a string (using the provided register name string for address lookup in the Device).

func (*DeviceType) RegReadRegAcc added in v0.0.4

func (Device *DeviceType) RegReadRegAcc(uAddr uint32, regAccOpt EevRegAccOpt) ([]byte, error)

RegReadRegAcc reads a register address using an EevRegAccOpt

func (*DeviceType) RegReadString added in v0.0.4

func (Device *DeviceType) RegReadString(uAddr uint32) (string, error)

RegString is used to read a register that contains a string

func (*DeviceType) RegReadU32 added in v0.0.4

func (Device *DeviceType) RegReadU32(uAddr uint32) (uint32, error)

RegReadU32 is used to read a register containing a uint32 value

func (*DeviceType) RegWriteRegAcc added in v0.0.12

func (Device *DeviceType) RegWriteRegAcc(uAddr uint32, regAccOpt EevRegAccOpt, wrData []byte) error

RegWriteRegAcc writes a register address using an EevRegAccOpt

func (*DeviceType) RegWriteU32 added in v0.0.4

func (Device *DeviceType) RegWriteU32(uAddr uint32, uVal uint32) error

RegWriteU32 writes a uint32 value to a register

func (*DeviceType) SPIdisable added in v0.0.12

func (Device *DeviceType) SPIdisable() error

Disable SPI controller

func (*DeviceType) SPIenable added in v0.0.12

func (Device *DeviceType) SPIenable() error

Enable SPI controller

func (*DeviceType) SPIerase added in v0.0.12

func (Device *DeviceType) SPIerase(chipSel uint8, addrSize uint8, addr uint32, eraseCmd uint8) error

Erase SPI flash with the provided Erase cmd and address

func (*DeviceType) SPIread added in v0.0.12

func (Device *DeviceType) SPIread(chipSel uint8, addrSize uint8, addr uint32, length uint32) ([]byte, error)

SPIread reads 1 to 256 bytes from the SPI flash starting at addr. It handles single-word transfers via spiTransfer and bulk reads via RegReadRegAcc.

func (*DeviceType) SPIreadDeviceID added in v0.0.12

func (Device *DeviceType) SPIreadDeviceID(chipSel uint8) (uint32, error)

Reads SPI flash Device ID (RDID command)

func (*DeviceType) SPIreadStatusReg added in v0.0.12

func (Device *DeviceType) SPIreadStatusReg(chipSel uint8) (uint8, error)

Read SPI flash Status Register

func (*DeviceType) SPIwrite added in v0.0.12

func (Device *DeviceType) SPIwrite(chipSel uint8, addrSize uint8, addr uint32, wrData []byte) error

SPIwrite writes 1 to 256 bytes to the SPI flash. It handles single-byte transfers via spiTransfer and bulk transfers via RegWriteRegAcc.

func (*DeviceType) SPIwriteAddr added in v0.0.12

func (Device *DeviceType) SPIwriteAddr(addrSize uint8, addr uint32) error

Write the address byte(s) to SPI flash

func (*DeviceType) SPIwriteCmd added in v0.0.12

func (Device *DeviceType) SPIwriteCmd(chipSel uint8, cmd uint8) error

Write SPI flash Command byte

func (*DeviceType) StreamMaxPktSize added in v0.0.9

func (Device *DeviceType) StreamMaxPktSize(streamNum string, destIP string, delay uint32) (uint16, error)

StreamMaxPktSize negotiates the largest usable packet size for the stream. It starts at 9000, decrements on failure, and increments back up when a good packet is received. Any size >= 200 that successfully delivers a packet is considered valid. If negotiation fails, it sets the device MaxPacketSize register to 1000

func (*DeviceType) StreamStart added in v0.0.6

func (Device *DeviceType) StreamStart(streamNum string, destIP string, destPort uint16, delay uint32, maxPkt uint16) error

Sets enable stream bit to start streaming on the provided stream number name (e.g. stream0). Also, configures streaming registers DestIPAddr, Delay, DestPort and MaxPacketSize. If the provided destPort value is 0 then a random, open dynamic port is assigned. If the provided maxPkt value is 0 then a system supported size is negotiated.

func (*DeviceType) StreamStop added in v0.0.6

func (Device *DeviceType) StreamStop(streamNum string) error

Clear enable stream bit to stop streaming on the provided stream number name (e.g. stream0)

func (*DeviceType) WriteReg added in v0.0.4

func (Device *DeviceType) WriteReg(regName string, uVal uint32) error

WriteReg is used to write a uint32 value to a register using the provided register name string for address lookup in the Device.

func (*DeviceType) WriteRegFields added in v0.0.4

func (Device *DeviceType) WriteRegFields(regName string, fVals map[string]uint32) error

WriteRegFields uses a register name string and writes the provide value(s) to the field(s)

type EevFeatureType added in v0.0.2

type EevFeatureType struct {
	Name      string        `yaml:"name"`
	ShortName string        `yaml:"sname"`
	Pointers  []PointerType `yaml:"pointers"`
}

type EevFeaturesStrType added in v0.0.2

type EevFeaturesStrType map[string]EevFeatureType

Features is a map from hex ID to Feature

type EevFeaturesType added in v0.0.2

type EevFeaturesType map[uint32]EevFeatureType

func LoadEevFeaturesFromYAML added in v0.0.5

func LoadEevFeaturesFromYAML() (EevFeaturesType, error)

Load master EEV features list

type EevRegAccOpt added in v0.0.2

type EevRegAccOpt struct {
	Insert bool
	Count  uint8
	Type   uint8
}

EevRegAccOpt struct used for creating a Register Access CoAP Option

type EevRegisterType added in v0.0.2

type EevRegisterType struct {
	Offset uint32               `yaml:"offset"`
	Name   string               `yaml:"name"`
	Access string               `yaml:"acc,omitempty"`
	Fields map[string]FieldType `yaml:"fields,omitempty"`
}

type FieldType added in v0.0.2

type FieldType struct {
	Msb uint32 `yaml:"msb"`
	Len uint32 `yaml:"len"`
}

type GetAccType

type GetAccType uint8
const (
	GetRegAccTypeReg     GetAccType = 0
	GetRegAccTypeFIFO    GetAccType = 1
	GetRegAccTypeRegIncr GetAccType = 4
	GetRegAccTypeString  GetAccType = 5
)

func (GetAccType) IsValid

func (accType GetAccType) IsValid() bool

type I2cRxDataType added in v0.0.6

type I2cRxDataType struct {
	Ack  uint32
	Data uint32
}

type ImageBuffer added in v0.0.7

type ImageBuffer struct {
	Data        []byte
	BlockID     uint32
	PacketID    uint32
	PayloadType uint16
	Width       uint32
	Height      uint32
	PixelFormat uint32
	Offset      uint32
}

ImageBuffer holds the frame data and info for assembling an image

type ImgCaptureResult added in v0.0.10

type ImgCaptureResult struct {
	Wg    *sync.WaitGroup
	ErrCh chan error
}

RawImgCaptureResult bundles WaitGroup and error channel

func ImgCapture added in v0.0.10

func ImgCapture(ctx context.Context, frameCount uint32, imagePath string, imageName string,
	dataCh <-chan *ImageBuffer) ImgCaptureResult

ImgCapture runs a background consumer go routine that saves N frames Returns WaitGroup that completes when done or canceled

type LocationType added in v0.0.2

type LocationType struct {
	IfName string `yaml:"ifName"`
	IfIP   string `yaml:"ifIP"`
	DevIP  string `yaml:"devIP"`
}

type PointerType added in v0.0.5

type PointerType struct {
	Index     int               `yaml:"index"`
	Name      string            `yaml:"name"`
	Registers []EevRegisterType `yaml:"registers"`
}

type PutAccType

type PutAccType uint8
const (
	PutRegAccTypeWr         PutAccType = 0
	PutRegAccTypeSet        PutAccType = 1
	PutRegAccTypeClear      PutAccType = 2
	PutRegAccTypeToggle     PutAccType = 3
	PutRegAccTypeWrIncr     PutAccType = 5
	PutRegAccTypeMaskWrIncr PutAccType = 6
	PutRegAccTypeRstAdvIncr PutAccType = 7
)

func (PutAccType) IsValid

func (accType PutAccType) IsValid() bool

type UDPListenerCfg added in v0.0.7

type UDPListenerCfg struct {
	Conn        *net.UDPConn
	LocalPort   int // The actual port we ended up listening on
	Interface   *net.Interface
	IsMulticast bool
}

UDPListenerCfg contains the returned items from the setupUDPListener function

Jump to

Keyboard shortcuts

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