diff --git a/system/rig_system.go b/system/rig_system.go index 8ef4216e..a7378b08 100644 --- a/system/rig_system.go +++ b/system/rig_system.go @@ -30,6 +30,7 @@ import ( "time" "github.com/ausocean/cloud/model" + "github.com/ausocean/cloud/system/camera" "github.com/ausocean/openfish/datastore" ) @@ -245,3 +246,78 @@ func PutRigSystem(ctx context.Context, store datastore.Store, system *RigSystem) return nil } + +// CameraSystem contains a camera device and the associated variables. +type CameraSystem struct { + Cam *model.Device + Vars []*model.Variable +} + +// SetWifi sets the wifi field of the camera. +func (sys *CameraSystem) SetWifi(ssid, pass string) { + sys.Cam.Wifi = ssid + "," + pass +} + +// SetLocation sets the location fields of the camera. +func (sys *CameraSystem) SetLocation(lat, long float64) { + sys.Cam.Latitude = lat + sys.Cam.Longitude = long +} + +// AddVariables adds the associated variables to the system. +func (sys *CameraSystem) AddVariables(variables ...*model.Variable) { + sys.Vars = variables +} + +// WithCameraDefaults applies all of the current defaults to the system. +func (sys *CameraSystem) WithCameraDefaults() { + sys.AddVariables( + model.NewAutoWhiteBalanceVar(camera.DefaultAutoWhiteBalance), + model.NewBitrateVar(camera.DefaultBitrate), + model.NewContrastVar(camera.DefaultContrast), + model.NewFrameRateVar(camera.DefaultFrameRate), + model.NewHDRVar(camera.DefaultHDR), + model.NewHeightVar(camera.DefaultHeight), + model.NewInputVar(camera.DefaultInput), + model.NewOutputVar(camera.DefaultOutput), + model.NewRotationVar(camera.DefaultRotation), + model.NewSaturationVar(camera.DefaultSaturation), + model.NewSharpnessVar(camera.DefaultSharpness), + model.NewWidthVar(camera.DefaultWidth), + model.NewLoggingVar(camera.DefaultLogging), + model.NewModeVar(camera.DefaultMode), + model.NewRTMPURLVar(""), + ) +} + +// NewCamera returns a new camera with the given name and mac address, with the given options applied. +func NewCamera(skey, dkey int64, name string, mac string, opts ...Option) (*CameraSystem, error) { + MAC := model.MacEncode(mac) + if MAC == 0 { + return nil, model.ErrInvalidMACAddress + } + + sys := &CameraSystem{ + Cam: &model.Device{ + Skey: skey, + Dkey: dkey, + Name: name, + Mac: MAC, + Type: model.DevTypeCamera, + }, + } + + for i, opt := range opts { + err := opt(sys) + if err != nil { + return nil, fmt.Errorf("unable to apply option (%d): %w", i, err) + } + } + + for _, variable := range sys.Vars { + variable.Skey = skey + variable.Scope = strings.ReplaceAll(sys.Cam.MAC(), ":", "") + } + + return sys, nil +} diff --git a/system/rig_system_test.go b/system/rig_system_test.go index 29acaa05..d123e4bc 100644 --- a/system/rig_system_test.go +++ b/system/rig_system_test.go @@ -2,11 +2,13 @@ package system_test import ( "reflect" + "strings" "testing" "time" "github.com/ausocean/cloud/model" "github.com/ausocean/cloud/system" + "github.com/stretchr/testify/assert" ) const ( @@ -441,6 +443,116 @@ func TestNewRigSystem(t *testing.T) { } } +func TestNewCameraSystem(t *testing.T) { + const ( + camName = "Test Cam Name" + testSSID = "test-ssid" + testPassword = "test-password" + testLat float64 = -16.443725 + testLong float64 = 147.898567 + ) + + tests := []struct { + name string + skey int64 + dkey int64 + mac string + cameraName string + options []system.Option + wantErr error + expectedCamera *model.Device + expectedVariables []*model.Variable + }{ + { + name: "New Camera no Options", + skey: testSiteKey, + dkey: testDevKey, + mac: strTestMAC, + cameraName: camName, + wantErr: nil, + expectedCamera: &model.Device{ + Name: camName, + Dkey: testDevKey, + Skey: testSiteKey, + Type: model.DevTypeCamera, + Mac: model.MacEncode(strTestMAC), + }, + }, + { + name: "New Camera with Wifi", + skey: testSiteKey, + dkey: testDevKey, + mac: strTestMAC, + cameraName: camName, + options: []system.Option{system.WithWifi(testSSID, testPassword)}, + wantErr: nil, + expectedCamera: &model.Device{ + Name: camName, + Dkey: testDevKey, + Skey: testSiteKey, + Type: model.DevTypeCamera, + Mac: model.MacEncode(strTestMAC), + Wifi: testSSID + "," + testPassword, + }, + }, + { + name: "New Camera with Location", + skey: testSiteKey, + dkey: testDevKey, + mac: strTestMAC, + cameraName: camName, + options: []system.Option{system.WithLocation(testLat, testLong)}, + wantErr: nil, + expectedCamera: &model.Device{ + Name: camName, + Dkey: testDevKey, + Skey: testSiteKey, + Type: model.DevTypeCamera, + Mac: model.MacEncode(strTestMAC), + Latitude: testLat, + Longitude: testLong, + }, + }, + { + name: "New Camera with Variable", + skey: testSiteKey, + dkey: testDevKey, + mac: strTestMAC, + cameraName: camName, + options: []system.Option{system.WithVariables([]*model.Variable{ + { + Name: "Test Var", + Value: "Default", + }, + }...)}, + wantErr: nil, + expectedCamera: &model.Device{ + Name: camName, + Dkey: testDevKey, + Skey: testSiteKey, + Type: model.DevTypeCamera, + Mac: model.MacEncode(strTestMAC), + }, + expectedVariables: []*model.Variable{ + { + Name: "Test Var", + Value: "Default", + Skey: testSiteKey, + Scope: strings.ReplaceAll(strTestMAC, ":", ""), + }, + }, + }, + } + + for _, tt := range tests { + sys, gotErr := system.NewCamera(tt.skey, tt.dkey, tt.cameraName, tt.mac, tt.options...) + + assert.ErrorIs(t, gotErr, tt.wantErr, "Test [%s] failed", tt.name) + assert.Equal(t, tt.expectedCamera, sys.Cam, "Test [%s] failed", tt.name) + assert.ElementsMatch(t, tt.expectedVariables, sys.Vars, "Test [%s] failed", tt.name) + } +} + // CompareSlices compares two slices of any type and checks for mismatched field values. func CompareSlices[T any](t *testing.T, gotSlice, wantSlice []*T, fields ...string) { if len(gotSlice) != len(wantSlice) {