Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions internal/homekit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ homekit:
dahua1: # same stream ID from streams list
pin: 12345678 # custom PIN, default: 19550224
name: Dahua camera # custom camera name, default: generated from stream ID
manufacturer: Dahua # custom manufacturer, default: AlexxIT
model: IPC-HDW1230T # custom model, default: go2rtc
serial_number: CAM-001 # custom serial number, default: -
firmware: "2.800" # custom firmware revision, default: go2rtc version
device_id: dahua1 # custom ID, default: generated from stream ID
device_private: dahua1 # custom key, default: generated from stream ID
speaker: true # enable 2-way audio (default: false, enable only if camera has a speaker)
Expand Down
8 changes: 8 additions & 0 deletions internal/homekit/homekit.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ func Init() {
Mod map[string]struct {
Pin string `yaml:"pin"`
Name string `yaml:"name"`
Manufacturer string `yaml:"manufacturer"`
Model string `yaml:"model"`
SerialNumber string `yaml:"serial_number"`
Firmware string `yaml:"firmware"`
DeviceID string `yaml:"device_id"`
DevicePrivate string `yaml:"device_private"`
CategoryID string `yaml:"category_id"`
Expand Down Expand Up @@ -84,6 +88,10 @@ func Init() {
StreamName: id,
Pin: conf.Pin,
Name: conf.Name,
Manufacturer: conf.Manufacturer,
Model: conf.Model,
SerialNumber: conf.SerialNumber,
Firmware: conf.Firmware,
DeviceID: conf.DeviceID,
DevicePrivate: conf.DevicePrivate,
CategoryID: conf.CategoryID,
Expand Down
8 changes: 6 additions & 2 deletions pkg/hksv/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,12 @@ type Config struct {
Speaker *bool // include Speaker service for 2-way audio (default false)

// Optional - metadata
UserAgent string // for mDNS TXTModel field
Version string // for accessory firmware version
Manufacturer string // accessory manufacturer (default "AlexxIT")
Model string // accessory model (default "go2rtc")
SerialNumber string // accessory serial number (default "-")
Firmware string // accessory firmware revision (defaults to Version)
UserAgent string // for mDNS TXTModel field
Version string // host version and default accessory firmware revision

// Optional - persistence and features
Store PairingStore // nil = pairings not persisted
Expand Down
22 changes: 19 additions & 3 deletions pkg/hksv/hksv.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ type Config struct {
StreamName string
Pin string // HomeKit pairing PIN (e.g., "27041991")
Name string // mDNS display name (auto-generated if empty)
Manufacturer string // accessory manufacturer (default "AlexxIT")
Model string // accessory model (default "go2rtc")
SerialNumber string // accessory serial number (default "-")
Firmware string // accessory firmware revision (defaults to Version)
DeviceID string // MAC-like device ID (auto-generated if empty)
DevicePrivate string // ed25519 private key hex (auto-generated if empty)
CategoryID string // "camera" or "doorbell"
Expand Down Expand Up @@ -161,6 +165,18 @@ func NewServer(cfg Config) (*Server, error) {
deviceID := CalcDeviceID(cfg.DeviceID, cfg.StreamName)
name := CalcName(cfg.Name, deviceID)
setupID := CalcSetupID(cfg.StreamName)
if cfg.Manufacturer == "" {
cfg.Manufacturer = "AlexxIT"
}
if cfg.Model == "" {
cfg.Model = "go2rtc"
}
if cfg.SerialNumber == "" {
cfg.SerialNumber = "-"
}
if cfg.Firmware == "" {
cfg.Firmware = cfg.Version
}

srv := &Server{
stream: cfg.StreamName,
Expand Down Expand Up @@ -213,12 +229,12 @@ func NewServer(cfg Config) (*Server, error) {
Float64("threshold", srv.motionThreshold).Msg("[hksv] HKSV mode")

if cfg.CategoryID == "doorbell" {
srv.accessory = camera.NewHKSVDoorbellAccessory("AlexxIT", "go2rtc", name, "-", cfg.Version)
srv.accessory = camera.NewHKSVDoorbellAccessory(cfg.Manufacturer, cfg.Model, name, cfg.SerialNumber, cfg.Firmware)
} else {
srv.accessory = camera.NewHKSVAccessory("AlexxIT", "go2rtc", name, "-", cfg.Version)
srv.accessory = camera.NewHKSVAccessory(cfg.Manufacturer, cfg.Model, name, cfg.SerialNumber, cfg.Firmware)
}
} else {
srv.accessory = camera.NewAccessory("AlexxIT", "go2rtc", name, "-", cfg.Version)
srv.accessory = camera.NewAccessory(cfg.Manufacturer, cfg.Model, name, cfg.SerialNumber, cfg.Firmware)
}

// Remove Speaker service unless explicitly enabled (default: disabled)
Expand Down
47 changes: 47 additions & 0 deletions pkg/hksv/hksv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,53 @@ func TestNewServer_CustomName(t *testing.T) {
require.Equal(t, "Living Room Camera", srv.MDNSEntry().Name)
}

func TestNewServer_AccessoryMetadata(t *testing.T) {
tests := []struct {
name string
hksv bool
categoryID string
}{
{name: "HomeKit"},
{name: "HKSV", hksv: true},
{name: "HKSV doorbell", hksv: true, categoryID: "doorbell"},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
srv := newTestServer(t, func(c *Config) {
c.HKSV = test.hksv
c.CategoryID = test.categoryID
c.Name = "Front Door"
c.Manufacturer = "Acme"
c.Model = "Camera X"
c.SerialNumber = "CAM-001"
c.Firmware = "2.3.4"
})

info := srv.Accessory().GetService("3E")
require.NotNil(t, info)
require.Equal(t, "Acme", info.GetCharacter("20").Value)
require.Equal(t, "Camera X", info.GetCharacter("21").Value)
require.Equal(t, "Front Door", info.GetCharacter("23").Value)
require.Equal(t, "CAM-001", info.GetCharacter("30").Value)
require.Equal(t, "2.3.4", info.GetCharacter("52").Value)
})
}
}

func TestNewServer_AccessoryMetadataDefaults(t *testing.T) {
srv := newTestServer(t, func(c *Config) {
c.Version = "1.2.3"
})

info := srv.Accessory().GetService("3E")
require.NotNil(t, info)
require.Equal(t, "AlexxIT", info.GetCharacter("20").Value)
require.Equal(t, "go2rtc", info.GetCharacter("21").Value)
require.Equal(t, "-", info.GetCharacter("30").Value)
require.Equal(t, "1.2.3", info.GetCharacter("52").Value)
}

func TestNewServer_CustomDeviceID(t *testing.T) {
srv := newTestServer(t, func(c *Config) {
c.DeviceID = "AA:BB:CC:DD:EE:FF"
Expand Down