package device import ( "time" "bytes" "text/template" "fmt" ) type DayOfWeek int func (d DayOfWeek) Next() DayOfWeek { if d == Sunday { return Monday } return d+1 } func (d DayOfWeek) Previous() DayOfWeek { if d == Monday { return Sunday } return d-1 } func (d DayOfWeek) DurationBetween(n DayOfWeek) time.Duration { // return duration between two day of week var duration time.Duration if (d-n == 0) { duration, _ = time.ParseDuration("168h") } else { duration, _ = time.ParseDuration(fmt.Sprintf("%dh", (d-n)*24 )) } return duration } const ( Monday DayOfWeek = 0 Thuesday = 1 Wednesday = 2 Thursday = 3 Friday = 4 Saturday = 5 Sunday = 6 ) func WeekDayEnToFr(weekday time.Weekday) DayOfWeek { // translate weekday to french week, start by Monday return map[time.Weekday]DayOfWeek { time.Monday : Monday, time.Tuesday : Thuesday, time.Wednesday: Wednesday, time.Thursday : Thursday, time.Friday: Friday, time.Saturday: Saturday, time.Sunday: Sunday, }[weekday] } func daytime(t time.Time) int { return t.Hour()*60 + t.Minute() } func weekday(t time.Time) DayOfWeek { return WeekDayEnToFr(t.Weekday()) } type Message struct { Payload []byte Topic string Retain bool } type Setpoint struct { Start int `json:"start"` Preset_id int `json:"preset_id"` } type WeekProgram map[DayOfWeek][]Setpoint func (p WeekProgram) Current() Setpoint { // return current Setpoint now := time.Now() weekday := weekday(now) daytime := daytime(now) setpoint := Setpoint{} for _, sp := range p[weekday] { if daytime < sp.Start { break } setpoint = sp } return 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{} for _, sp := range p[weekday] { setpoint = sp if daytime < sp.Start { return setpoint } } return Setpoint{} } startweekday := weekday for (setpoint == Setpoint{}) { setpoint = get(weekday, daytime) if (setpoint != Setpoint{}) { // setpoint found, compute time next := t.Add( startweekday.DurationBetween(weekday) ) next = t.Add( time.Duration(setpoint.Start - daytime ) * 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 next, nil } type Programs map[string]WeekProgram type Preset struct { Label string `json:"label"` Value int `json:"value"` Color string `json:"color"` } type TVRSettings struct { Setpoint_topic string `json:"setpoint_topic"` Setpoint_payload string `json:"setpoint_payload"` Setpoint_state_topic string `json:"setpoint_state_topic"` Setpoint_state_jp string `json:"setpoint_state_jp"` } func (s TVRSettings) FormatTopicState(device_name string) (string, error) { type Variable struct { Device string } variables := Variable{device_name} t, err := template.New("topic").Parse(s.Setpoint_state_topic) if err != nil { return "", err } buf := new(bytes.Buffer) err = t.Execute(buf, variables) if err != nil { return "", err } return buf.String(), nil } func (s TVRSettings) FormatTopic(device_name string) (string, error) { type Variable struct { Device string } variables := Variable{device_name} t, err := template.New("topic").Parse(s.Setpoint_topic) if err != nil { return "", err } buf := new(bytes.Buffer) err = t.Execute(buf, variables) if err != nil { return "", err } return buf.String(), nil } func (s TVRSettings) FormatPayload(setpoint int) (string, error) { type Variable struct { Setpoint int } variables := Variable{setpoint} t, err := template.New("payload").Parse(s.Setpoint_payload) if err != nil { return "", err } buf := new(bytes.Buffer) err = t.Execute(buf, variables) if err != nil { return "", err } return buf.String(), nil } type DeviceSettings struct { Programs Programs `json:"programs"` Presets []Preset `json:"presets"` TVR TVRSettings `json:"TVR"` }