Skip to content

Commit

Permalink
feat: Add interface methods to ScheduleTimetable object
Browse files Browse the repository at this point in the history
  • Loading branch information
gonzolino committed Mar 18, 2022
1 parent 32982d4 commit 819ef45
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 77 deletions.
66 changes: 16 additions & 50 deletions examples/schedule/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"context"
"fmt"
"net/http"
"os"
"time"

Expand Down Expand Up @@ -35,72 +34,42 @@ func main() {
homeName, zoneName := os.Args[1], os.Args[2]

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)
}

// Find zone to control
zones, err := gotado.GetZones(client, home)
zone, err := home.GetZone(ctx, zoneName)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get zones: %v\n", err)
os.Exit(1)
}
var zone *gotado.Zone
for _, z := range zones {
if z.Name == zoneName {
zone = z
break
}
}
if zone == nil {
fmt.Fprintf(os.Stderr, "Zone '%s' not found\n", zoneName)
fmt.Fprintf(os.Stderr, "Failed to find zone '%s': %v\n", zoneName, err)
os.Exit(1)
}

// Show schedule timetables
timetables, err := gotado.GetTimetables(client, home, zone)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to list available heating schedule timetables: %v\n", err)
os.Exit(1)
}
fmt.Println("Available heating schedule timetables:")
for _, timetable := range timetables {
for _, timetable := range []*gotado.ScheduleTimetable{zone.TimetableMonToSun(), zone.TimetableMonToFriSatSun(), zone.TimetableAllDays()} {
fmt.Printf("%s (%d)\n", timetable.Type, timetable.ID)
}
activeTimetable, err := gotado.GetActiveTimetable(client, home, zone)
activeTimetable, err := zone.GetActiveTimetable(ctx)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get active heating schedule timetable: %v\n", err)
os.Exit(1)
}
fmt.Printf("Active heating schedule timetable: %s (%d)\n", activeTimetable.Type, activeTimetable.ID)

// Get and print schedule
schedule, err := gotado.GetSchedule(client, home, zone, activeTimetable)
schedule, err := activeTimetable.GetScheduleTimeBlocks(ctx)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get heating schedule: %v\n", err)
os.Exit(1)
Expand All @@ -115,11 +84,8 @@ func main() {
}

// Update schedule
newTimetable := &gotado.ScheduleTimetable{
ID: 0,
Type: "ONE_DAY",
}
newSchedule := []*gotado.ScheduleBlock{
newTimetable := zone.TimetableMonToSun()
newSchedule := []*gotado.ScheduleTimeBlock{
{
DayType: "MONDAY_TO_SUNDAY",
Start: "00:00",
Expand Down Expand Up @@ -157,11 +123,11 @@ func main() {
},
},
}
if err := gotado.SetActiveTimetable(client, home, zone, newTimetable); err != nil {
if err := zone.SetActiveTimetable(ctx, newTimetable); err != nil {
fmt.Fprintf(os.Stderr, "Failed to set active heating schedule timetable: %v\n", err)
os.Exit(1)
}
if err := gotado.SetSchedule(client, home, zone, newTimetable, newSchedule); err != nil {
if err := newTimetable.SetScheduleTimeBlocks(ctx, newSchedule); err != nil {
fmt.Fprintf(os.Stderr, "Failed to set heating schedule: %v\n", err)
os.Exit(1)
}
Expand All @@ -170,11 +136,11 @@ func main() {
time.Sleep(10 * time.Second)

// Restore original heating schedule
if err := gotado.SetActiveTimetable(client, home, zone, activeTimetable); err != nil {
if err := zone.SetActiveTimetable(ctx, activeTimetable); err != nil {
fmt.Fprintf(os.Stderr, "Failed to set active heating schedule timetable: %v\n", err)
os.Exit(1)
}
if err := gotado.SetSchedule(client, home, zone, activeTimetable, schedule); err != nil {
if err := activeTimetable.SetScheduleTimeBlocks(ctx, schedule); err != nil {
fmt.Fprintf(os.Stderr, "Failed to set heating schedule: %v\n", err)
os.Exit(1)
}
Expand Down
30 changes: 3 additions & 27 deletions models.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,35 +327,11 @@ type WeatherMeasurement struct {
// ScheduleTimetable is the type of a tado° schedule timetable
type ScheduleTimetable struct {
client *client
zone *Zone
ID int32 `json:"id"`
Type string `json:"type,omitempty"`
}

// TimetableMonToSun has the same schedule for all days between monday and sunday
func TimetableMonToSun() *ScheduleTimetable {
return &ScheduleTimetable{
ID: 0,
Type: "ONE_DAY",
}
}

// TimetableTMonToFriSatSun has the same schedule for all days between monday
// and friday and different schedules for saturday and sunday
func TimetableMonToFriSatSun() *ScheduleTimetable {
return &ScheduleTimetable{
ID: 1,
Type: "THREE_DAY",
}
}

// TimetableAllDays has a different schedule for each day of the week
func TimetableAllDays() *ScheduleTimetable {
return &ScheduleTimetable{
ID: 2,
Type: "SEVEN_DAY",
}
}

// DayType specifies the type of day for a heating schedule block
type DayType string

Expand All @@ -371,8 +347,8 @@ const (
DayTypeSunday DayType = "SUNDAY"
)

// ScheduleBlock is a block in a tado° schedule
type ScheduleBlock struct {
// ScheduleTimeBlock is a block in a tado° schedule
type ScheduleTimeBlock struct {
DayType DayType `json:"dayType"`
Start string `json:"start"`
End string `json:"end"`
Expand Down
32 changes: 32 additions & 0 deletions schedule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package gotado

import "context"

// GetScheduleTimeBlocks returns all time blocks of the timetable schedule.
func (s *ScheduleTimetable) GetScheduleTimeBlocks(ctx context.Context) ([]*ScheduleTimeBlock, error) {
blocks := make([]*ScheduleTimeBlock, 0)
if err := s.client.get(ctx, apiURL("homes/%d/zones/%d/schedule/timetables/%d/blocks", s.zone.home.ID, s.zone.ID, s.ID), &blocks); err != nil {
return nil, err
}
return blocks, nil
}

func (s *ScheduleTimetable) SetScheduleTimeBlocks(ctx context.Context, schedule []*ScheduleTimeBlock) error {
// Order schedule blocks by day types.
// For each daytipe we want to send one put request.
scheduleMap := map[DayType][]*ScheduleTimeBlock{}
for _, scheduleBlock := range schedule {
if _, ok := scheduleMap[scheduleBlock.DayType]; !ok {
scheduleMap[scheduleBlock.DayType] = make([]*ScheduleTimeBlock, 0, 1)
}
scheduleMap[scheduleBlock.DayType] = append(scheduleMap[scheduleBlock.DayType], scheduleBlock)
}

for dayType, scheduleBlocks := range scheduleMap {
if err := s.client.put(ctx, apiURL("homes/%d/zones/%d/schedule/timetables/%d/blocks/%s", s.zone.home.ID, s.zone.ID, s.ID, dayType), scheduleBlocks); err != nil {
return err
}
}

return nil
}
28 changes: 28 additions & 0 deletions zone.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,40 @@ func (z *Zone) SetEarlyStart(ctx context.Context, earlyStart bool) error {
return z.client.put(ctx, apiURL("homes/%d/zones/%d/earlyStart", z.home.ID, z.ID), &EarlyStart{Enabled: earlyStart})
}

// newScheduleTimetable creates a new schedule timetable linked to the zone.
func (z *Zone) newScheduleTimetable(id int32, typ string) *ScheduleTimetable {
return &ScheduleTimetable{
client: z.client,
zone: z,
ID: id,
Type: typ,
}
}

// TimetableMonToSun has the same schedule for all days between monday and sunday.
func (z *Zone) TimetableMonToSun() *ScheduleTimetable {
return z.newScheduleTimetable(0, "ONE_DAY")
}

// TimetableTMonToFriSatSun has the same schedule for all days between monday
// and friday and different schedules for saturday and sunday.
func (z *Zone) TimetableMonToFriSatSun() *ScheduleTimetable {
return z.newScheduleTimetable(1, "THREE_DAY")
}

// TimetableAllDays has a different schedule for each day of the week.
func (z *Zone) TimetableAllDays() *ScheduleTimetable {
return z.newScheduleTimetable(2, "SEVEN_DAY")
}

// GetActiveTimetable returns the active schedule timetable for the zone.
func (z *Zone) GetActiveTimetable(ctx context.Context) (*ScheduleTimetable, error) {
timetable := &ScheduleTimetable{}
if err := z.client.get(ctx, apiURL("homes/%d/zones/%d/schedule/activeTimetable", z.home.ID, z.ID), timetable); err != nil {
return nil, err
}
timetable.client = z.client
timetable.zone = z
return timetable, nil
}

Expand Down

0 comments on commit 819ef45

Please sign in to comment.