From 11b3622abe04441130538f8d03d72f501615417f Mon Sep 17 00:00:00 2001 From: Nicolas Duhamel Date: Fri, 28 Oct 2022 16:14:47 +0200 Subject: [PATCH] Fix until_next and add test --- main.go | 13 ++++--------- pkg/device/device_test.go | 34 ++++++++++++++++++++++++++++------ pkg/device/settings.go | 31 +++++++++++++++---------------- pkg/device/settings_test.go | 31 ++++++++++++++++++++++++++++--- 4 files changed, 75 insertions(+), 34 deletions(-) diff --git a/main.go b/main.go index 76923d3..153ad66 100644 --- a/main.go +++ b/main.go @@ -150,6 +150,7 @@ func (app *App) onSettingsMessage(ctx context.Context, msg mqttpaho.Message) { func (app *App) onSetStateMessage(ctx context.Context, msg mqttpaho.Message) { // callback for topic /{prefix}/{tvr_id}/state/set change's + device_name := strings.Split(msg.Topic(), "/")[1] logger := zerolog.Ctx(ctx).With(). @@ -172,16 +173,10 @@ func (app *App) onSetStateMessage(ctx context.Context, msg mqttpaho.Message) { return } - if !device.SameState(state) { - device.State = state + if err := device.SetState(&logger, state, app.PubChan); err != nil { + logger.Error().Err(err).Msg("") + return - err := app.DeviceManager.Check(ctx, device_name) - if err != nil { - logger.Error().Err(err).Msg("error while checking device") - } - // device.SetState(log, state, pubchan) - } else { - logger.Info().Msg("no state update, ignoring") } } diff --git a/pkg/device/device_test.go b/pkg/device/device_test.go index 661ba89..a036031 100644 --- a/pkg/device/device_test.go +++ b/pkg/device/device_test.go @@ -317,6 +317,8 @@ func TestUpdate(t *testing.T) { // device 3: currentSetpoint 0 always, 22 // device 4: currentSetpoint 22 until_time, fixed at timeNow, for 2h 22 // device 5: currentSetpoint 17 indem 4 but fixed timeNow-2h + // device 6: currentSetpoint 17, until_next set a timeNow, test time time now +1h : no change + timeNow = func() time.Time { return test_time @@ -362,36 +364,56 @@ func TestUpdate(t *testing.T) { Until_time: timeNow().Add(-1*time.Minute), } + device6 := test_device + device6.Name = "6" + device6.CurrentSetpoint = 22 + device6.State = DeviceState{ + Mode: "until_next", + Setpoint: 22, + Time: timeNow(), + } + + var tests = []struct{ + getTime func() time.Time device Device want []Message change bool err error }{ - {device1, []Message{ + {timeNow, device1, []Message{ Message{ Payload: []byte("{\"current_heating_setpoint\": 17}"), Topic: "zigbee2mqtt/TVR/1/set", Retain: false, }, }, true, nil} , - {device2, []Message{}, false, Error("device 2 don't have unknown program")}, - {device3, []Message{ + {timeNow, device2, []Message{}, false, Error("device 2 don't have unknown program")}, + {timeNow, device3, []Message{ Message{ Payload: []byte("{\"current_heating_setpoint\": 22}"), Topic: "zigbee2mqtt/TVR/3/set", Retain: false, }, }, true, nil} , - {device4, []Message{}, false, nil} , - {device5, []Message{}, true, nil} , + {timeNow, device4, []Message{}, false, nil} , + {timeNow, device5, []Message{}, true, nil} , + {timeNow, device6, []Message{}, false, nil} , + {func()time.Time{return test_time.Add(7*time.Hour+30*time.Minute)}, device6, []Message{ + Message{ + Payload: []byte("{\"current_heating_setpoint\": 19}"), + Topic: "zigbee2mqtt/TVR/6/set", + Retain: false, + }, + }, true, nil} , } for _, tt := range tests { testname := fmt.Sprintf("%s", tt.device.Name ) t.Run(testname, func(t *testing.T) { - result := []Message{} + timeNow = tt.getTime + result := []Message{} rchan := make(chan Message, 10) errchan := make(chan error, 1) diff --git a/pkg/device/settings.go b/pkg/device/settings.go index 7270d20..f21650b 100644 --- a/pkg/device/settings.go +++ b/pkg/device/settings.go @@ -104,42 +104,41 @@ func (p WeekProgram) Current() Setpoint { func (p WeekProgram) NextTime(t time.Time) (time.Time, error) { // return next program change - setpoint := Setpoint{} - var next time.Time weekday := weekday(t) daytime := daytime(t) // Recursive func to find setpoint on weekday - get := func (weekday DayOfWeek, daytime int) Setpoint { - setpoint := Setpoint{} + get := func (weekday DayOfWeek, daytime int) (Setpoint, bool) { for _, sp := range p[weekday] { - setpoint = sp - if daytime < sp.Start { - return setpoint + if daytime <= sp.Start { + return sp, true } } - return Setpoint{} + return Setpoint{}, false } startweekday := weekday - for (setpoint == Setpoint{}) { - setpoint = get(weekday, daytime) - if (setpoint != Setpoint{}) { - // setpoint found, compute time - next := time.Date(t.Year(), t.Month(), t.Day() + startweekday.DaysBetween(weekday), 0, 0, 0, 0, time.Local) + for { + if setpoint, ok := get(weekday, daytime); ok { + next := time.Date(t.Year(), + t.Month(), + t.Day() + startweekday.DaysBetween(weekday), + 0, 0, 0, 0, + time.Local) - next = next.Add(time.Duration( (setpoint.Start) * int(time.Minute) )) + next = next.Add( + time.Duration( (setpoint.Start) * int(time.Minute) )) return next, nil } + weekday = weekday.Next() daytime = 0 if weekday == startweekday { - return next, fmt.Errorf("Shouldn't happen no setpoint found over the week") + return time.Time{}, fmt.Errorf("Shouldn't happen no setpoint found over the week") } } - return next, nil } type Programs map[string]WeekProgram diff --git a/pkg/device/settings_test.go b/pkg/device/settings_test.go index 685e72f..684b5a7 100644 --- a/pkg/device/settings_test.go +++ b/pkg/device/settings_test.go @@ -39,7 +39,12 @@ func TestNextTime(t *testing.T) { {Start: 22*60, Preset_id: 0}, } - program := WeekProgram{ + zeroSetpoints := []Setpoint{ + {Start: 0, Preset_id: 0}, + } + + + default_program := WeekProgram{ Monday: defaultSetpoints, Thuesday: defaultSetpoints, Wednesday: defaultSetpoints, @@ -49,29 +54,49 @@ func TestNextTime(t *testing.T) { Sunday: defaultSetpoints, } + zero_program := WeekProgram{ + Monday: zeroSetpoints, + Thuesday: zeroSetpoints, + Wednesday: zeroSetpoints, + Thursday : zeroSetpoints, + Friday: zeroSetpoints, + Saturday: zeroSetpoints, + Sunday: zeroSetpoints, + } + + var tests = []struct{ + prog WeekProgram time time.Time want time.Time }{ { + default_program, time.Date(2022, time.October, 23, 9, 0, 0, 0, time.Local), time.Date(2022, time.October, 23, 16, 0, 0, 0, time.Local), }, { + default_program, time.Date(2022, time.October, 24, 5, 0, 0, 0, time.Local), time.Date(2022, time.October, 24, 7, 0, 0, 0, time.Local), }, { + default_program, time.Date(2022, time.October, 23, 23, 0, 0, 0, time.Local), time.Date(2022, time.October, 24, 7, 0, 0, 0, time.Local), }, + { + zero_program, + time.Date(2022, time.October, 23, 23, 0, 0, 0, time.Local), + time.Date(2022, time.October, 24, 0, 0, 0, 0, time.Local), + }, } for _, tt := range tests { testname := fmt.Sprintf("%s", tt.time.String() ) t.Run(testname, func(t *testing.T) { - next, err := program.NextTime(tt.time) + next, err := tt.prog.NextTime(tt.time) if err != nil { - t.Fatalf("unexpected error") + t.Fatalf(err.Error()) } if !next.Equal(tt.want) { t.Errorf("got %s, want %s", next.String(), tt.want.String())