From cdd2c69c688365e5600510acb4f900fdae472c94 Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Date: Sun, 13 Feb 2022 23:02:55 +0100 Subject: [PATCH] feat: Add interface methods to Home object --- examples/mischomeinfo/main.go | 36 +++-------- examples/presence/main.go | 37 ++++-------- home.go | 111 ++++++++++++++++++++++++++++++++++ models.go | 3 + 4 files changed, 135 insertions(+), 52 deletions(-) create mode 100644 home.go diff --git a/examples/mischomeinfo/main.go b/examples/mischomeinfo/main.go index 6873acc..1df4c65 100644 --- a/examples/mischomeinfo/main.go +++ b/examples/mischomeinfo/main.go @@ -3,9 +3,7 @@ package main import ( "context" "fmt" - "net/http" "os" - "time" "github.com/gonzolino/gotado" ) @@ -35,37 +33,23 @@ func main() { homeName := os.Args[1] ctx := context.Background() + tado := gotado.New(clientID, clientSecret) - // Create authenticated tado° client - httpClient := &http.Client{Timeout: 5 * time.Second} - client := gotado.NewClient(clientID, clientSecret).WithHTTPClient(httpClient) - client, err := client.WithCredentials(ctx, username, password) - if err != nil { - fmt.Fprintf(os.Stderr, "Authentication failed: %v\n", err) - os.Exit(1) - } - - user, err := gotado.GetMe(client) + user, err := tado.Me(ctx, username, password) if err != nil { fmt.Fprintf(os.Stderr, "Failed to get user info: %v\n", err) os.Exit(1) } // Find the home to control - var home *gotado.UserHome - for _, h := range user.Homes { - if h.Name == homeName { - home = &h - break - } - } - if home == nil { - fmt.Fprintf(os.Stderr, "Home '%s' not found\n", homeName) + home, err := user.GetHome(ctx, homeName) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to find home '%s': %v\n", homeName, err) os.Exit(1) } // Get weather - weather, err := gotado.GetWeather(client, home) + weather, err := home.GetWeather(ctx) fmt.Println("Weather:") if err != nil { fmt.Fprintf(os.Stderr, "Failed to get weather: %v\n", err) @@ -76,7 +60,7 @@ func main() { fmt.Printf("Weather State: %s\n", weather.WeatherState.Value) // Get Devices - devices, err := gotado.GetDevices(client, home) + devices, err := home.GetDevices(ctx) if err != nil { fmt.Fprintf(os.Stderr, "Failed to get devices: %v\n", err) os.Exit(1) @@ -87,7 +71,7 @@ func main() { } // Get Installations - installations, err := gotado.GetInstallations(client, home) + installations, err := home.GetInstallations(ctx) if err != nil { fmt.Fprintf(os.Stderr, "Failed to get installations: %v\n", err) os.Exit(1) @@ -98,7 +82,7 @@ func main() { } // Get mobile Devices - mobileDevices, err := gotado.GetMobileDevices(client, home) + mobileDevices, err := home.GetMobileDevices(ctx) if err != nil { fmt.Fprintf(os.Stderr, "Failed to get mobile devices: %v\n", err) os.Exit(1) @@ -113,7 +97,7 @@ func main() { } // Get Users - users, err := gotado.GetUsers(client, home) + users, err := home.GetUsers(ctx) if err != nil { fmt.Fprintf(os.Stderr, "Failed to get users: %v\n", err) os.Exit(1) diff --git a/examples/presence/main.go b/examples/presence/main.go index 97de26d..0165e4c 100644 --- a/examples/presence/main.go +++ b/examples/presence/main.go @@ -3,7 +3,6 @@ package main import ( "context" "fmt" - "net/http" "os" "time" @@ -35,37 +34,23 @@ func main() { homeName := os.Args[1] ctx := context.Background() + tado := gotado.New(clientID, clientSecret) - // Create authenticated tado° client - httpClient := &http.Client{Timeout: 5 * time.Second} - client := gotado.NewClient(clientID, clientSecret).WithHTTPClient(httpClient) - client, err := client.WithCredentials(ctx, username, password) - if err != nil { - fmt.Fprintf(os.Stderr, "Authentication failed: %v\n", err) - os.Exit(1) - } - - user, err := gotado.GetMe(client) + user, err := tado.Me(ctx, username, password) if err != nil { fmt.Fprintf(os.Stderr, "Failed to get user info: %v\n", err) os.Exit(1) } // Find the home to control - var home *gotado.UserHome - for _, h := range user.Homes { - if h.Name == homeName { - home = &h - break - } - } - if home == nil { - fmt.Fprintf(os.Stderr, "Home '%s' not found\n", homeName) + home, err := user.GetHome(ctx, homeName) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to find home '%s': %v\n", homeName, err) os.Exit(1) } // Get current presence from home state - state, err := gotado.GetHomeState(client, home) + state, err := home.GetState(ctx) if err != nil { fmt.Fprintf(os.Stderr, "Failed to get home state: %v\n", err) os.Exit(1) @@ -78,7 +63,7 @@ func main() { } // Lock presence to 'away' - if err := gotado.SetPresenceAway(client, home); err != nil { + if err := home.SetPresenceAway(ctx); err != nil { fmt.Fprintf(os.Stderr, "Failed to set presence 'away': %v", err) os.Exit(1) } @@ -87,7 +72,7 @@ func main() { time.Sleep(10 * time.Second) // Lock presence to 'at home' - if err := gotado.SetPresenceHome(client, home); err != nil { + if err := home.SetPresenceHome(ctx); err != nil { fmt.Fprintf(os.Stderr, "Failed to set presence 'home': %v", err) os.Exit(1) } @@ -96,7 +81,7 @@ func main() { time.Sleep(10 * time.Second) // Set auto presence - if err := gotado.SetPresenceAuto(client, home); err != nil { + if err := home.SetPresenceAuto(ctx); err != nil { fmt.Fprintf(os.Stderr, "Failed to set presence 'auto': %v", err) os.Exit(1) } @@ -108,9 +93,9 @@ func main() { if state.PresenceLocked { switch state.Presence { case "HOME": - err = gotado.SetPresenceHome(client, home) + err = home.SetPresenceHome(ctx) case "AWAY": - err = gotado.SetPresenceAway(client, home) + err = home.SetPresenceAway(ctx) } if err != nil { diff --git a/home.go b/home.go new file mode 100644 index 0000000..d0b8809 --- /dev/null +++ b/home.go @@ -0,0 +1,111 @@ +package gotado + +import ( + "context" + "fmt" +) + +// GetHomeState returns the state of the home +func (h *Home) GetState(ctx context.Context) (*HomeState, error) { + homeState := &HomeState{} + if err := h.client.get(ctx, apiURL("homes/%d/state", h.ID), homeState); err != nil { + return nil, err + } + return homeState, nil +} + +// GetZones returns information about the zones in the home +func (h *Home) GetZones(ctx context.Context) ([]*Zone, error) { + zones := make([]*Zone, 0) + if err := h.client.get(ctx, apiURL("homes/%d/zones", h.ID), &zones); err != nil { + return nil, err + } + for _, zone := range zones { + zone.client = h.client + } + return zones, nil +} + +func (h *Home) GetZone(ctx context.Context, name string) (*Zone, error) { + zones, err := h.GetZones(ctx) + if err != nil { + return nil, fmt.Errorf("unable to list zones: %w", err) + } + for _, zone := range zones { + if zone.Name == name { + return zone, nil + } + } + return nil, fmt.Errorf("unknown zone name '%s'", name) +} + +// GetWeather returns weather information at the homes location +func (h *Home) GetWeather(ctx context.Context) (*Weather, error) { + weather := &Weather{} + if err := h.client.get(ctx, apiURL("homes/%d/weather", h.ID), weather); err != nil { + return nil, err + } + return weather, nil +} + +// GetDevices lists all devices in the home +func (h *Home) GetDevices(ctx context.Context) ([]*Device, error) { + devices := make([]*Device, 0) + if err := h.client.get(ctx, apiURL("homes/%d/devices", h.ID), &devices); err != nil { + return nil, err + } + for _, device := range devices { + device.client = h.client + } + return devices, nil +} + +// GetInstallations lists all installations in the home +func (h *Home) GetInstallations(ctx context.Context) ([]*Installation, error) { + installations := make([]*Installation, 0) + if err := h.client.get(ctx, apiURL("homes/%d/installations", h.ID), &installations); err != nil { + return nil, err + } + return installations, nil +} + +// GetMobileDevices lists all mobile devices linked to the home +func (h *Home) GetMobileDevices(ctx context.Context) ([]*MobileDevice, error) { + mobileDevices := make([]*MobileDevice, 0) + if err := h.client.get(ctx, apiURL("homes/%d/mobileDevices", h.ID), &mobileDevices); err != nil { + return nil, err + } + for _, mobileDevice := range mobileDevices { + mobileDevice.client = h.client + } + return mobileDevices, nil +} + +// GetUsers lists all users and their mobile devices linked to the home +func (h *Home) GetUsers(ctx context.Context) ([]*User, error) { + users := make([]*User, 0) + if err := h.client.get(ctx, apiURL("homes/%d/users", h.ID), &users); err != nil { + return nil, err + } + for _, user := range users { + user.client = h.client + } + return users, nil +} + +// SetPresenceHome sets the geofencing presence to 'at home'. +func (h *Home) SetPresenceHome(ctx context.Context) error { + presence := PresenceLock{HomePresence: PresenceHome} + return h.client.put(ctx, apiURL("homes/%d/presenceLock", h.ID), presence) +} + +// SetPresenceAway sets the geofencing presence to 'away'. +func (h *Home) SetPresenceAway(ctx context.Context) error { + presence := PresenceLock{HomePresence: PresenceAway} + return h.client.put(ctx, apiURL("homes/%d/presenceLock", h.ID), presence) +} + +// SetPresenceAuto enables geofencing auto mode. +func (h *Home) SetPresenceAuto(ctx context.Context) error { + return h.client.delete(ctx, apiURL("homes/%d/presenceLock", h.ID)) +} diff --git a/models.go b/models.go index 268049e..3ea7879 100644 --- a/models.go +++ b/models.go @@ -121,6 +121,7 @@ const ( // Zone represents a tado° zone type Zone struct { + client *client ID int32 `json:"id"` Name string `json:"name"` Type ZoneType `json:"type"` @@ -400,6 +401,7 @@ type Weather struct { // Device represents a tado° device such as a thermostat or a bridge type Device struct { + client *client DeviceType DeviceType `json:"deviceType"` SerialNo string `json:"serialNo"` ShortSerialNo string `json:"shortSerialNo"` @@ -442,6 +444,7 @@ type Installation struct { // MobileDevice represents a mobile device with the tado° app installed type MobileDevice struct { + client *client Name string `json:"name"` ID int32 `json:"id"` Settings MobileDeviceSettings `json:"settings"`