2018-09-22 19:22:42 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018 Jeffrey Walter <jeffreydwalter@gmail.com>
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
|
|
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
|
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
|
|
|
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
|
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
|
|
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
|
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
|
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2018-09-19 07:07:32 +00:00
|
|
|
package arlo
|
2017-12-09 03:55:38 +00:00
|
|
|
|
2017-12-10 19:17:09 +00:00
|
|
|
// A Device is the device data, this can be a camera, basestation, arloq, etc.
|
2017-12-09 03:55:38 +00:00
|
|
|
type Device struct {
|
2018-09-19 19:12:06 +00:00
|
|
|
arlo *Arlo // Let's hold a reference to the parent arlo object since it holds the http.Client object and references to all devices.
|
|
|
|
AnalyticsEnabled bool `json:"analyticsEnabled"`
|
|
|
|
ArloMobilePlan bool `json:"arloMobilePlan"`
|
|
|
|
ArloMobilePlanId string `json:"arloMobilePlanId"`
|
|
|
|
ArloMobilePlanName string `json:"arloMobilePlanName"`
|
|
|
|
ArloMobilePlanThreshold int `json:"arloMobilePlanThreshold"`
|
|
|
|
Connectivity Connectivity `json:"connectivity"`
|
|
|
|
CriticalBatteryState bool `json:"criticalBatteryState"`
|
2018-09-20 22:38:01 +00:00
|
|
|
DateCreated int64 `json:"dateCreated"`
|
2018-09-19 19:12:06 +00:00
|
|
|
DeviceId string `json:"deviceId"`
|
|
|
|
DeviceName string `json:"deviceName"`
|
|
|
|
DeviceType string `json:"deviceType"`
|
|
|
|
DisplayOrder uint8 `json:"displayOrder"`
|
|
|
|
FirmwareVersion string `json:"firmwareVersion"`
|
|
|
|
InterfaceVersion string `json:"interfaceVersion"`
|
|
|
|
InterfaceSchemaVer string `json:"interfaceSchemaVer"`
|
|
|
|
LastImageUploaded string `json:"lastImageUploaded"`
|
2018-09-20 22:38:01 +00:00
|
|
|
LastModified int64 `json:"lastModified"`
|
2018-09-19 19:12:06 +00:00
|
|
|
MigrateActivityZone bool `json:"migrateActivityZone"`
|
|
|
|
MobileCarrier string `json:"mobileCarrier"`
|
|
|
|
MobileTrialUsed bool `json:"mobileTrialUsed"`
|
|
|
|
PermissionsFilePath string `json:"permissionsFilePath"`
|
|
|
|
PermissionsSchemaVer string `json:"permissionsSchemaVer"`
|
|
|
|
PermissionsVerison string `json:"permissionsVerison"` // WTF? Netgear developers think this is OK... *sigh*
|
|
|
|
PermissionsVersion string `json:"permissionsVersion"`
|
|
|
|
PresignedFullFrameSnapshotUrl string `json:"presignedFullFrameSnapshotUrl"`
|
|
|
|
PresignedLastImageUrl string `json:"presignedLastImageUrl"`
|
|
|
|
PresignedSnapshotUrl string `json:"presignedSnapshotUrl"`
|
|
|
|
MediaObjectCount uint8 `json:"mediaObjectCount"`
|
|
|
|
ModelId string `json:"modelId"`
|
|
|
|
Owner Owner `json:"owner"`
|
|
|
|
ParentId string `json:"parentId"`
|
|
|
|
Properties Properties `json:"properties"`
|
|
|
|
UniqueId string `json:"uniqueId"`
|
|
|
|
UserId string `json:"userId"`
|
|
|
|
UserRole string `json:"userRole"`
|
|
|
|
State string `json:"state"`
|
|
|
|
XCloudId string `json:"xCloudId"`
|
2017-12-09 03:55:38 +00:00
|
|
|
}
|
|
|
|
|
2018-09-22 19:22:42 +00:00
|
|
|
// Devices is a slice of Device objects.
|
2017-12-09 03:55:38 +00:00
|
|
|
type Devices []Device
|
|
|
|
|
2017-12-10 19:17:09 +00:00
|
|
|
// A DeviceOrder holds a map of device ids and a numeric index. The numeric index is the device order.
|
|
|
|
// Device order is mainly used by the UI to determine which order to show the devices.
|
2017-12-09 03:55:38 +00:00
|
|
|
/*
|
|
|
|
{
|
|
|
|
"devices":{
|
|
|
|
"XXXXXXXXXXXXX":1,
|
|
|
|
"XXXXXXXXXXXXX":2,
|
|
|
|
"XXXXXXXXXXXXX":3
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
type DeviceOrder struct {
|
2017-12-10 19:17:09 +00:00
|
|
|
Devices map[string]int `json:"devices"`
|
2017-12-09 03:55:38 +00:00
|
|
|
}
|
|
|
|
|
2017-12-10 19:17:09 +00:00
|
|
|
// Find returns a device with the device id passed in.
|
2017-12-09 03:55:38 +00:00
|
|
|
func (ds *Devices) Find(deviceId string) *Device {
|
|
|
|
for _, d := range *ds {
|
|
|
|
if d.DeviceId == deviceId {
|
|
|
|
return &d
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-09-22 19:22:42 +00:00
|
|
|
func (ds Devices) FindCameras(basestationId string) Cameras {
|
2018-09-17 04:44:41 +00:00
|
|
|
cs := new(Cameras)
|
2018-09-22 19:22:42 +00:00
|
|
|
for _, d := range ds {
|
2018-09-17 04:44:41 +00:00
|
|
|
if d.ParentId == basestationId {
|
|
|
|
*cs = append(*cs, Camera(d))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-19 19:12:06 +00:00
|
|
|
return *cs
|
2018-09-17 04:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d Device) IsBasestation() bool {
|
2018-09-19 19:12:06 +00:00
|
|
|
return d.DeviceType == DeviceTypeBasestation || d.DeviceId == d.ParentId
|
2018-09-17 04:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d Device) IsCamera() bool {
|
|
|
|
return d.DeviceType == DeviceTypeCamera
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetBasestations returns a Basestations object containing all devices that are NOT type "camera".
|
2017-12-10 19:17:09 +00:00
|
|
|
// I did this because some device types, like arloq, don't have a basestation.
|
|
|
|
// So, when interacting with them you must treat them like a basestation and a camera.
|
2018-09-17 04:44:41 +00:00
|
|
|
// Cameras also includes devices of this type, so you can get the same data there or cast.
|
2018-09-22 19:22:42 +00:00
|
|
|
func (ds Devices) GetBasestations() *Basestations {
|
|
|
|
basestations := new(Basestations)
|
2018-09-19 19:12:06 +00:00
|
|
|
for _, d := range ds {
|
|
|
|
if d.IsBasestation() || !d.IsCamera() {
|
2018-09-22 19:22:42 +00:00
|
|
|
*basestations = append(*basestations, Basestation{Device: d})
|
2017-12-09 03:55:38 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-17 04:44:41 +00:00
|
|
|
return basestations
|
2017-12-09 03:55:38 +00:00
|
|
|
}
|
|
|
|
|
2018-09-17 04:44:41 +00:00
|
|
|
// GetCameras returns a Cameras object containing all devices that are of type "camera".
|
2017-12-10 19:17:09 +00:00
|
|
|
// I did this because some device types, like arloq, don't have a basestation.
|
|
|
|
// So, when interacting with them you must treat them like a basestation and a camera.
|
2018-09-19 19:12:06 +00:00
|
|
|
// Basestations also includes devices of this type, so you can get the same data there or cast.
|
2018-09-22 19:22:42 +00:00
|
|
|
func (ds Devices) GetCameras() *Cameras {
|
|
|
|
cameras := new(Cameras)
|
2018-09-19 19:12:06 +00:00
|
|
|
for _, d := range ds {
|
|
|
|
if d.IsCamera() || !d.IsBasestation() {
|
2018-09-22 19:22:42 +00:00
|
|
|
*cameras = append(*cameras, Camera(d))
|
2017-12-09 03:55:38 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-17 04:44:41 +00:00
|
|
|
return cameras
|
2017-12-09 03:55:38 +00:00
|
|
|
}
|
2017-12-10 19:17:09 +00:00
|
|
|
|
|
|
|
// UpdateDeviceName sets the name of the given device to the name argument.
|
2018-09-19 19:12:06 +00:00
|
|
|
func (d *Device) UpdateDeviceName(name string) error {
|
2017-12-10 19:17:09 +00:00
|
|
|
body := map[string]string{"deviceId": d.DeviceId, "deviceName": name, "parentId": d.ParentId}
|
2018-12-11 23:48:51 +00:00
|
|
|
resp, err := d.arlo.put(RenameDeviceUri, d.XCloudId, body, nil)
|
2018-09-20 22:38:01 +00:00
|
|
|
return checkRequest(resp, err, "failed to update device name")
|
2017-12-10 19:17:09 +00:00
|
|
|
}
|