arlo-go/arlo.go
2020-05-27 15:35:02 +04:00

182 lines
4.0 KiB
Go

package arlo
import (
"context"
"fmt"
"sync"
"time"
"github.com/go-resty/resty/v2"
)
type Arlo struct {
user string
pass string
client *resty.Client
Account Account
Basestations Basestations
Cameras Cameras
rwmutex sync.RWMutex
}
func NewArlo() (arlo *Arlo) {
c := resty.New().
SetHostURL(BaseUrl).
SetTimeout(30 * time.Second)
return &Arlo{
client: c,
}
}
func (a *Arlo) get(url string, result interface{}) error {
var errorResponse ErrorResponse
resp, err := a.client.R().
SetResult(result).
SetError(&errorResponse).
Get(url)
if err != nil {
return err
}
if resp.IsError() {
return fmt.Errorf(errorResponse.Reason)
}
return nil
}
func (a *Arlo) post(url string, body interface{}, result interface{}, xcloudId string) error {
var errorResponse ErrorResponse
request := a.client.R().
SetBody(body).
SetResult(result).
SetError(&errorResponse)
if xcloudId != "" {
request.SetHeader("xcloudId", xcloudId)
}
resp, err := request.Post(url)
if err != nil {
return err
}
if resp.IsError() {
return fmt.Errorf(errorResponse.Reason)
}
return nil
}
func (a *Arlo) put(url string, result interface{}, xcloudId string) error {
var errorResponse ErrorResponse
request := a.client.R().
SetResult(result).
SetError(&errorResponse)
if xcloudId != "" {
request.SetHeader("xcloudId", xcloudId)
}
resp, err := request.Put(url)
if err != nil {
return err
}
if resp.IsError() {
return fmt.Errorf(errorResponse.Reason)
}
return nil
}
func (a *Arlo) Login(ctx context.Context, user string, pass string) error {
var loginResponse LoginResponse
err := a.post(LoginV2Uri, map[string]string{
"email": user,
"password": pass,
}, &loginResponse, "")
if err != nil {
return fmt.Errorf("posting login request: %v", err)
}
if !loginResponse.Success {
return fmt.Errorf("no success but no error")
}
a.client.SetHeader("Authorization", loginResponse.Data.Token)
a.Account = loginResponse.Data
if _, err := a.GetDevices(ctx); err != nil {
return fmt.Errorf("getting devices: %v", err)
}
return nil
}
func (a *Arlo) Logout() error {
var response BaseResponse
err := a.put(LogoutUri, &response, "")
if err != nil {
return err
}
if !response.Success {
return fmt.Errorf("no success but no error")
}
return nil
}
func (a *Arlo) GetSession() (*Session, error) {
var response SessionResponse
err := a.get(SessionUri, &response)
if err != nil {
return nil, err
}
if !response.Success {
return nil, fmt.Errorf("no success but no error")
}
return &response.Data, nil
}
func (a *Arlo) GetDevices(ctx context.Context) (*Devices, error) {
var response DeviceResponse
err := a.get(fmt.Sprintf(DevicesUri, time.Now().Format("20060102")), &response)
if err != nil {
return nil, err
}
if !response.Success {
return nil, fmt.Errorf("no success but no error")
}
if len(response.Data) == 0 {
return nil, fmt.Errorf("no device found")
}
// Cache a pointer to the arlo object with each device.
for i := range response.Data {
response.Data[i].arlo = a
}
// Disconnect all of the basestations from the EventStream.
for _, basestation := range a.Basestations {
if err := basestation.Disconnect(); err != nil {
return nil, fmt.Errorf("disconnecting device %s: %v", basestation.DeviceName, err)
}
}
a.rwmutex.Lock()
// Cache the devices as their respective types.
a.Cameras = response.Data.GetCameras()
a.Basestations = response.Data.GetBasestations()
a.rwmutex.Unlock()
// subscribe each basestation to the EventStream.
for _, basestation := range a.Basestations {
if err := basestation.Subscribe(ctx); err != nil {
return nil, fmt.Errorf("subscribing device %s: %v", basestation.DeviceName, err)
}
}
return &response.Data, nil
}
// GetProfile returns the user profile for the currently logged in user.
func (a *Arlo) GetProfile() (*UserProfile, error) {
var response UserProfileResponse
err := a.get(ProfileUri, &response)
if err != nil {
return nil, err
}
if !response.Success {
return nil, fmt.Errorf("no success but no error")
}
return &response.Data, nil
}