Fix until_next and add test

This commit is contained in:
Nicolas Duhamel 2022-10-28 16:14:47 +02:00
parent b5906d06bd
commit 11b3622abe
4 changed files with 75 additions and 34 deletions

13
main.go
View File

@ -150,6 +150,7 @@ func (app *App) onSettingsMessage(ctx context.Context, msg mqttpaho.Message) {
func (app *App) onSetStateMessage(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 // callback for topic /{prefix}/{tvr_id}/state/set change's
device_name := strings.Split(msg.Topic(), "/")[1] device_name := strings.Split(msg.Topic(), "/")[1]
logger := zerolog.Ctx(ctx).With(). logger := zerolog.Ctx(ctx).With().
@ -172,16 +173,10 @@ func (app *App) onSetStateMessage(ctx context.Context, msg mqttpaho.Message) {
return return
} }
if !device.SameState(state) { if err := device.SetState(&logger, state, app.PubChan); err != nil {
device.State = state 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")
} }
} }

View File

@ -317,6 +317,8 @@ func TestUpdate(t *testing.T) {
// device 3: currentSetpoint 0 always, 22 // device 3: currentSetpoint 0 always, 22
// device 4: currentSetpoint 22 until_time, fixed at timeNow, for 2h 22 // device 4: currentSetpoint 22 until_time, fixed at timeNow, for 2h 22
// device 5: currentSetpoint 17 indem 4 but fixed timeNow-2h // 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 { timeNow = func() time.Time {
return test_time return test_time
@ -362,35 +364,55 @@ func TestUpdate(t *testing.T) {
Until_time: timeNow().Add(-1*time.Minute), 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{ var tests = []struct{
getTime func() time.Time
device Device device Device
want []Message want []Message
change bool change bool
err error err error
}{ }{
{device1, []Message{ {timeNow, device1, []Message{
Message{ Message{
Payload: []byte("{\"current_heating_setpoint\": 17}"), Payload: []byte("{\"current_heating_setpoint\": 17}"),
Topic: "zigbee2mqtt/TVR/1/set", Topic: "zigbee2mqtt/TVR/1/set",
Retain: false, Retain: false,
}, },
}, true, nil} , }, true, nil} ,
{device2, []Message{}, false, Error("device 2 don't have unknown program")}, {timeNow, device2, []Message{}, false, Error("device 2 don't have unknown program")},
{device3, []Message{ {timeNow, device3, []Message{
Message{ Message{
Payload: []byte("{\"current_heating_setpoint\": 22}"), Payload: []byte("{\"current_heating_setpoint\": 22}"),
Topic: "zigbee2mqtt/TVR/3/set", Topic: "zigbee2mqtt/TVR/3/set",
Retain: false, Retain: false,
}, },
}, true, nil} , }, true, nil} ,
{device4, []Message{}, false, nil} , {timeNow, device4, []Message{}, false, nil} ,
{device5, []Message{}, true, 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 { for _, tt := range tests {
testname := fmt.Sprintf("%s", tt.device.Name ) testname := fmt.Sprintf("%s", tt.device.Name )
t.Run(testname, func(t *testing.T) { t.Run(testname, func(t *testing.T) {
timeNow = tt.getTime
result := []Message{} result := []Message{}
rchan := make(chan Message, 10) rchan := make(chan Message, 10)

View File

@ -104,42 +104,41 @@ func (p WeekProgram) Current() Setpoint {
func (p WeekProgram) NextTime(t time.Time) (time.Time, error) { func (p WeekProgram) NextTime(t time.Time) (time.Time, error) {
// return next program change // return next program change
setpoint := Setpoint{}
var next time.Time
weekday := weekday(t) weekday := weekday(t)
daytime := daytime(t) daytime := daytime(t)
// Recursive func to find setpoint on weekday // Recursive func to find setpoint on weekday
get := func (weekday DayOfWeek, daytime int) Setpoint { get := func (weekday DayOfWeek, daytime int) (Setpoint, bool) {
setpoint := Setpoint{}
for _, sp := range p[weekday] { for _, sp := range p[weekday] {
setpoint = sp if daytime <= sp.Start {
if daytime < sp.Start { return sp, true
return setpoint
} }
} }
return Setpoint{} return Setpoint{}, false
} }
startweekday := weekday startweekday := weekday
for (setpoint == Setpoint{}) { for {
setpoint = get(weekday, daytime) if setpoint, ok := get(weekday, daytime); ok {
if (setpoint != Setpoint{}) { next := time.Date(t.Year(),
// setpoint found, compute time t.Month(),
next := time.Date(t.Year(), t.Month(), t.Day() + startweekday.DaysBetween(weekday), 0, 0, 0, 0, time.Local) 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 return next, nil
} }
weekday = weekday.Next() weekday = weekday.Next()
daytime = 0 daytime = 0
if weekday == startweekday { 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 type Programs map[string]WeekProgram

View File

@ -39,7 +39,12 @@ func TestNextTime(t *testing.T) {
{Start: 22*60, Preset_id: 0}, {Start: 22*60, Preset_id: 0},
} }
program := WeekProgram{ zeroSetpoints := []Setpoint{
{Start: 0, Preset_id: 0},
}
default_program := WeekProgram{
Monday: defaultSetpoints, Monday: defaultSetpoints,
Thuesday: defaultSetpoints, Thuesday: defaultSetpoints,
Wednesday: defaultSetpoints, Wednesday: defaultSetpoints,
@ -49,29 +54,49 @@ func TestNextTime(t *testing.T) {
Sunday: defaultSetpoints, Sunday: defaultSetpoints,
} }
zero_program := WeekProgram{
Monday: zeroSetpoints,
Thuesday: zeroSetpoints,
Wednesday: zeroSetpoints,
Thursday : zeroSetpoints,
Friday: zeroSetpoints,
Saturday: zeroSetpoints,
Sunday: zeroSetpoints,
}
var tests = []struct{ var tests = []struct{
prog WeekProgram
time time.Time time time.Time
want 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, 9, 0, 0, 0, time.Local),
time.Date(2022, time.October, 23, 16, 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, 5, 0, 0, 0, time.Local),
time.Date(2022, time.October, 24, 7, 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, 23, 23, 0, 0, 0, time.Local),
time.Date(2022, time.October, 24, 7, 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 { for _, tt := range tests {
testname := fmt.Sprintf("%s", tt.time.String() ) testname := fmt.Sprintf("%s", tt.time.String() )
t.Run(testname, func(t *testing.T) { t.Run(testname, func(t *testing.T) {
next, err := program.NextTime(tt.time) next, err := tt.prog.NextTime(tt.time)
if err != nil { if err != nil {
t.Fatalf("unexpected error") t.Fatalf(err.Error())
} }
if !next.Equal(tt.want) { if !next.Equal(tt.want) {
t.Errorf("got %s, want %s", next.String(), tt.want.String()) t.Errorf("got %s, want %s", next.String(), tt.want.String())