arlo-go/arloclient.go

289 lines
9.3 KiB
Go
Raw Normal View History

2017-11-30 22:50:40 +00:00
package arloclient
import (
"log"
"time"
"github.com/jeffreydwalter/arloclient/internal/request"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
)
type Arlo struct {
user string
pass string
client *request.Client
account Account
}
func NewArlo(user string, pass string) (*Arlo, error) {
c, _ := request.NewClient(BaseUrl)
arlo := &Arlo{
user: user,
pass: pass,
client: c,
}
if _, err := arlo.Login(); err != nil {
return nil, errors.WithMessage(err, "failed to create arlo object")
}
return arlo, nil
}
func (a *Arlo) Login() (*Account, error) {
resp, err := a.client.Post(LoginUri, Credentials{Email: a.user, Password: a.pass}, nil)
if err != nil {
return nil, errors.WithMessage(err, "failed to login")
}
var loginResponse LoginResponse
if err := mapstructure.Decode(resp.Data, &loginResponse); err != nil {
return nil, errors.Wrap(err, "failed to create loginresponse object")
}
if !loginResponse.Success {
return nil, errors.New("request was unsuccessful")
}
// Cache the auth token.
a.client.BaseHttpHeader.Add("Authorization", loginResponse.Data.Token)
// Save the account info with the Arlo struct.
a.account = loginResponse.Data
return &loginResponse.Data, nil
}
func (a *Arlo) Logout() (*request.Response, error) {
return a.client.Put(LogoutUri, nil, nil)
}
func (a *Arlo) GetDevices() (*Devices, error) {
resp, err := a.client.Get(DevicesUri, nil)
if err != nil {
return nil, errors.WithMessage(err, "failed to get devices")
}
var deviceResponse DeviceResponse
if err := mapstructure.Decode(resp.Data, &deviceResponse); err != nil {
return nil, errors.Wrap(err, "failed to create deviceresponse object")
}
if !deviceResponse.Success {
return nil, errors.New("request was unsuccessful")
}
return &deviceResponse.Data, nil
}
func (a *Arlo) GetLibraryMetaData(fromDate, toDate time.Time) (*LibraryMetaData, error) {
resp, err := a.client.Post(LibraryMetadataUri, Duration{fromDate.Format("20060102"), toDate.Format("20060102")}, nil)
if err != nil {
return nil, errors.WithMessage(err, "failed to get library metadata")
}
log.Printf("GETLIBRARYMETADATA: %v", resp.Data)
var libraryMetaDataResponse LibraryMetaDataResponse
if err := mapstructure.Decode(resp.Data, &libraryMetaDataResponse); err != nil {
return nil, errors.WithMessage(err, "failed to create librarymetadataresponse object")
}
if !libraryMetaDataResponse.Success {
return nil, errors.New("request was unsuccessful")
}
return &libraryMetaDataResponse.Data, nil
}
func (a *Arlo) UpdateProfile(firstName, lastName string) (*UserProfile, error) {
resp, err := a.client.Put(UserProfileUri, FullName{firstName, lastName}, nil)
if err != nil {
return nil, err
}
var userProfileResponse UserProfileResponse
if err := mapstructure.Decode(resp.Data, &userProfileResponse); err != nil {
return nil, err
}
if !userProfileResponse.Success {
return nil, err
}
return &userProfileResponse.Data, nil
}
func (a *Arlo) UpdatePassword(password string) error {
_, err := a.client.Post(UserChangePasswordUri, PasswordPair{a.pass, password}, nil)
if err != nil {
a.pass = password
}
return err
}
/*
##
# This is an example of the json you would pass in the body to UpdateFriends():
#{
# "firstName":"Some",
# "lastName":"Body",
# "devices":{
# "XXXXXXXXXXXXX":"Camera 1",
# "XXXXXXXXXXXXX":"Camera 2 ",
# "XXXXXXXXXXXXX":"Camera 3"
# },
# "lastModified":1463977440911,
# "adminUser":true,
# "email":"user@example.com",
# "id":"XXX-XXXXXXX"
#}
##
func (a *Arlo) UpdateFriends(body):
return a.client.Put('https://arlo.netgear.com/hmsweb/users/friends', body)
func (a *Arlo) UpdateDeviceName(device, name):
return a.client.Put('https://arlo.netgear.com/hmsweb/users/devices/renameDevice', {'deviceId':device.get('deviceId'), 'deviceName':name, 'parentId':device.get('parentId')})
##
# This is an example of the json you would pass in the body to UpdateDisplayOrder() of your devices in the UI.
#
# XXXXXXXXXXXXX is the device id of each camera. You can get this from GetDevices().
#{
# "devices":{
# "XXXXXXXXXXXXX":1,
# "XXXXXXXXXXXXX":2,
# "XXXXXXXXXXXXX":3
# }
#}
##
func (a *Arlo) UpdateDisplayOrder(body):
return a.client.Post('https://arlo.netgear.com/hmsweb/users/devices/displayOrder', body)
##
# This call returns the following:
# presignedContentUrl is a link to the actual video in Amazon AWS.
# presignedThumbnailUrl is a link to the thumbnail .jpg of the actual video in Amazon AWS.
#
#[
# {
# "mediaDurationSecond": 30,
# "contentType": "video/mp4",
# "name": "XXXXXXXXXXXXX",
# "presignedContentUrl": "https://arlos3-prod-z2.s3.amazonaws.com/XXXXXXX_XXXX_XXXX_XXXX_XXXXXXXXXXXXX/XXX-XXXXXXX/XXXXXXXXXXXXX/recordings/XXXXXXXXXXXXX.mp4?AWSAccessKeyId=XXXXXXXXXXXXXXXXXXXX&Expires=1472968703&Signature=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
# "lastModified": 1472881430181,
# "localCreatedDate": XXXXXXXXXXXXX,
# "presignedThumbnailUrl": "https://arlos3-prod-z2.s3.amazonaws.com/XXXXXXX_XXXX_XXXX_XXXX_XXXXXXXXXXXXX/XXX-XXXXXXX/XXXXXXXXXXXXX/recordings/XXXXXXXXXXXXX_thumb.jpg?AWSAccessKeyId=XXXXXXXXXXXXXXXXXXXX&Expires=1472968703&Signature=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
# "reason": "motionRecord",
# "deviceId": "XXXXXXXXXXXXX",
# "createdBy": "XXXXXXXXXXXXX",
# "createdDate": "20160903",
# "timeZone": "America/Chicago",
# "ownerId": "XXX-XXXXXXX",
# "utcCreatedDate": XXXXXXXXXXXXX,
# "currentState": "new",
# "mediaDuration": "00:00:30"
# }
#]
##
func (a *Arlo) GetLibrary(from_date, to_date):
return a.client.Post('https://arlo.netgear.com/hmsweb/users/library', {'dateFrom':from_date, 'dateTo':to_date})
##
# Delete a single video recording from Arlo.
#
# All of the date info and device id you need to pass into this method are given in the results of the GetLibrary() call.
#
##
func (a *Arlo) DeleteRecording(camera, created_date, utc_created_date):
return a.client.Post('https://arlo.netgear.com/hmsweb/users/library/recycle', {'data':[{'createdDate':created_date,'utcCreatedDate':utc_created_date,'deviceId':camera.get('deviceId')}]})
##
# Delete a batch of video recordings from Arlo.
#
# The GetLibrary() call response json can be passed directly to this method if you'd like to delete the same list of videos you queried for.
# If you want to delete some other batch of videos, then you need to send an array of objects representing each video you want to delete.
#
#[
# {
# "createdDate":"20160904",
# "utcCreatedDate":1473010280395,
# "deviceId":"XXXXXXXXXXXXX"
# },
# {
# "createdDate":"20160904",
# "utcCreatedDate":1473010280395,
# "deviceId":"XXXXXXXXXXXXX"
# }
#]
##
func (a *Arlo) BatchDeleteRecordings(recording_metadata):
return a.client.Post('https://arlo.netgear.com/hmsweb/users/library/recycle', {'data':recording_metadata})
##
# Returns the whole video from the presignedContentUrl.
#
# Obviously, this function is generic and could be used to download anything. :)
##
func (a *Arlo) GetRecording(url, chunk_size=4096):
video = ''
r = requests.get(url, stream=True)
r.raise_for_status()
for chunk in r.iter_content(chunk_size):
if chunk: video += chunk
return video
##
# This function returns a json object containing the rtmps url to the requested video stream.
# You will need the to install a library to handle streaming of this protocol: https://pypi.python.org/pypi/python-librtmp
#
# The request to /users/devices/startStream returns:
#{ "url":"rtmps://vzwow09-z2-prod.vz.netgear.com:80/vzmodulelive?egressToken=b1b4b675_ac03_4182_9844_043e02a44f71&userAgent=web&cameraId=48B4597VD8FF5_1473010750131" }
#
##
func (a *Arlo) StartStream(camera):
return a.client.Post('https://arlo.netgear.com/hmsweb/users/devices/startStream', {"to":camera.get('parentId'),"from":self.user_id+"_web","resource":"cameras/"+camera.get('deviceId'),"action":"set","publishResponse":True,"transId":self.genTransId(),"properties":{"activityState":"startUserStream","cameraId":camera.get('deviceId')}}, headers={"xcloudId":camera.get('xCloudId')})
##
# This function causes the camera to record a snapshot.
#
# You can get the timezone from GetDevices().
##
func (a *Arlo) TakeSnapshot(camera):
stream_url = self.StartStream(camera)
a.client.Post('https://arlo.netgear.com/hmsweb/users/devices/takeSnapshot', {'xcloudId':camera.get('xCloudId'),'parentId':camera.get('parentId'),'deviceId':camera.get('deviceId'),'olsonTimeZone':camera.get('properties', {}).get('olsonTimeZone')}, headers={"xcloudId":camera.get('xCloudId')})
return stream_url;
##
# This function causes the camera to start recording.
#
# You can get the timezone from GetDevices().
##
func (a *Arlo) StartRecording(camera):
stream_url = self.StartStream(camera)
a.client.Post('https://arlo.netgear.com/hmsweb/users/devices/startRecord', {'xcloudId':camera.get('xCloudId'),'parentId':camera.get('parentId'),'deviceId':camera.get('deviceId'),'olsonTimeZone':camera.get('properties', {}).get('olsonTimeZone')}, headers={"xcloudId":camera.get('xCloudId')})
return stream_url
##
# This function causes the camera to stop recording.
#
# You can get the timezone from GetDevices().
##
func (a *Arlo) StopRecording(camera):
return a.client.Post('https://arlo.netgear.com/hmsweb/users/devices/stopRecord', {'xcloudId':camera.get('xCloudId'),'parentId':camera.get('parentId'),'deviceId':camera.get('deviceId'),'olsonTimeZone':camera.get('properties', {}).get('olsonTimeZone')}, headers={"xcloudId":camera.get('xCloudId')})
*/