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
27 changes: 25 additions & 2 deletions cmd/aver/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ func main() {
handlers := handlers.NewCameraController(cs)
handlers.Logger = log
handlers.CreateCamera = func(ctx context.Context, addr string) (cameraservices.Camera, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

// TODO need to make this function better if New() does much of anything (see av-control-api/drivers)
if cam, ok := cameras.Load(addr); ok {
return cam.(*aver.Pro520), nil
Expand All @@ -157,11 +160,31 @@ func main() {
}
}

username, password, err := cs.FindCameraAuthByAddress(ctx, addrNoPort)
if err != nil {
log.Warn("unable to get camera credentials from config service, falling back to flags",
zap.String("camera", addrNoPort),
zap.Error(err),
)
username = camUsername
password = camPassword
}

if username == "" {
log.Debug("no username provided for camera, using default")
username = camUsername
}

if password == "" {
log.Debug("no password provided for camera, using default")
password = camPassword
}

cam := &aver.Pro520{
Camera: visca.New(addr, visca.WithLogger(log.Sugar().Named(addr))),
Address: addrNoPort,
Username: camUsername,
Password: camPassword,
Username: username,
Password: password,
}

cameras.Store(addr, cam)
Expand Down
4 changes: 3 additions & 1 deletion control.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ type CameraConfig struct {
Presets []CameraPreset `json:"presets"`

// admin items
Reboot string `json:"reboot"`
Reboot string `json:"reboot"`
UserName string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
}

type CameraPreset struct {
Expand Down
84 changes: 84 additions & 0 deletions couch/couch.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package couch
import (
"context"
"fmt"
"net"
"strings"

cameraservices "github.com/byuoitav/camera-services"
Expand Down Expand Up @@ -191,3 +192,86 @@ func (c *configService) ControlIP(ctx context.Context, room string) ([]string, e

return IP, nil
}

// FindCameraByAddress searches the config database for a camera with the given address
// and returns its username and password.
func (c *configService) FindCameraAuthByAddress(ctx context.Context, addr string) (string, string, error) {
db := c.client.DB(ctx, c.uiConfigDB)

query := map[string]interface{}{
"selector": map[string]interface{}{
"presets": map[string]interface{}{
"$elemMatch": map[string]interface{}{
"cameras": map[string]interface{}{
"$elemMatch": map[string]interface{}{
"$or": []map[string]interface{}{
{"stream": map[string]interface{}{"$regex": addr}},
{"panLeft": map[string]interface{}{"$regex": addr}},
{"panRight": map[string]interface{}{"$regex": addr}},
{"tiltUp": map[string]interface{}{"$regex": addr}},
{"tiltDown": map[string]interface{}{"$regex": addr}},
},
},
},
},
},
},
}

rows, err := db.Find(ctx, query)
if err != nil {
return "", "", fmt.Errorf("unable to query config DB: %w", err)
}
for rows.Next() {
var config uiConfig
if err := rows.ScanDoc(&config); err != nil {
continue
}
for _, group := range config.ControlGroups {
for _, cam := range group.Cameras {
if strings.Contains(cam.Stream, addr) || strings.Contains(cam.PanLeft, addr) ||
strings.Contains(cam.PanRight, addr) || strings.Contains(cam.TiltUp, addr) ||
strings.Contains(cam.TiltDown, addr) {
return cam.UserName, cam.Password, nil
}
}
}
}
return "", "", fmt.Errorf("camera with address %s not found", addr)
}

// GetCameraAuth retrieves the camera's username and password from the config database based on the provided address.
func (c *configService) GetCameraAuth(ctx context.Context, addr string) (string, string, error) {
isIP := net.ParseIP(addr) != nil
if !isIP {
// Tries to get room from hostname in address
parts := strings.SplitN(addr, "-", 3)
if len(parts) >= 2 {
roomID := parts[0] + "-" + parts[1]
var config uiConfig

db := c.client.DB(ctx, c.uiConfigDB)
if err := db.Get(ctx, roomID).ScanDoc(&config); err == nil {
for _, group := range config.ControlGroups {
for _, cam := range group.Cameras {
if cameraMatchesAddress(cam, addr) {
return cam.UserName, cam.Password, nil
}
}
}
}
}
}

// If it fails to get a room from the address, it will try to get the camera from the config database
// by searching all the docs for the address
return c.FindCameraAuthByAddress(ctx, addr)
}

func cameraMatchesAddress(cam cameraservices.CameraConfig, addr string) bool {
return strings.Contains(cam.Stream, addr) ||
strings.Contains(cam.PanLeft, addr) ||
strings.Contains(cam.PanRight, addr) ||
strings.Contains(cam.TiltUp, addr) ||
strings.Contains(cam.TiltDown, addr)
}