diff --git a/internal/homekit/README.md b/internal/homekit/README.md index 8b0bac841..bb8e9a85e 100644 --- a/internal/homekit/README.md +++ b/internal/homekit/README.md @@ -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) diff --git a/internal/homekit/homekit.go b/internal/homekit/homekit.go index 5eb75d1e1..c8e6d7c7c 100644 --- a/internal/homekit/homekit.go +++ b/internal/homekit/homekit.go @@ -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"` @@ -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, diff --git a/pkg/hksv/README.md b/pkg/hksv/README.md index 99b77b5be..4c02b2718 100644 --- a/pkg/hksv/README.md +++ b/pkg/hksv/README.md @@ -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 diff --git a/pkg/hksv/hksv.go b/pkg/hksv/hksv.go index 23bf06b5c..aef7137d1 100644 --- a/pkg/hksv/hksv.go +++ b/pkg/hksv/hksv.go @@ -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" @@ -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, @@ -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) diff --git a/pkg/hksv/hksv_test.go b/pkg/hksv/hksv_test.go index 2315a2393..7d10612bb 100644 --- a/pkg/hksv/hksv_test.go +++ b/pkg/hksv/hksv_test.go @@ -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"