207 lines
4.8 KiB
Go
207 lines
4.8 KiB
Go
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"`
|
|
}
|