forked from bpicode/fritzctl
/
temperature.go
123 lines (109 loc) · 3.69 KB
/
temperature.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package cmd
import (
"fmt"
"strconv"
"strings"
"github.com/coolduke/fritzctl/fritz"
"github.com/coolduke/fritzctl/logger"
"github.com/spf13/cobra"
)
var temperatureCmd = &cobra.Command{
Use: "temperature [value in °C, on, off, sav, comf] [device/group names]",
Short: "Set the temperature of HKR devices/groups or turn them on/off",
Long: "Change the temperature of HKR devices/groups by supplying the desired value in °C. " +
"When turning HKR devices on/off, replace the value by 'on'/'off' respectively." +
"To reset each devices to its comfort/saving temperature, replace the value by 'comf'/'sav'." +
"To increase/decrease temperatures relative to the current goal, supply '+' or '-' followed by space.",
Example: `fritzctl temperature 21.0 HKR_1 HKR_2
fritzctl temperature off HKR_1
fritzctl temperature on HKR_2
fritzctl temperature comf HK1 HKR_2
fritzctl temperature sav HK1 HKR_2
fritzctl temperature + 1.5 HK1
fritzctl temperature - 2 HK1
`,
RunE: changeTemperature,
}
func init() {
RootCmd.AddCommand(temperatureCmd)
}
func changeTemperature(_ *cobra.Command, args []string) error {
assertMinLen(args, 2, "insufficient input: at least two parameters expected (run with --help for more details)")
val := args[0]
action := changeAction(val)
action(val, args[1:]...)
logger.Info("It may take a few minutes until the changes propagate to the end device(s)")
return nil
}
func changeAction(s string) func(val string, args ...string) {
if strings.EqualFold(s, "sav") || strings.EqualFold(s, "saving") {
return changeToSav
}
if strings.EqualFold(s, "comf") || strings.EqualFold(s, "comfort") {
return changeToComf
}
if s == "+" || s == "-" {
return changeBy
}
return changeTo
}
func changeToSav(_ string, args ...string) {
changeByCallback(func(t fritz.Thermostat) string {
return t.FmtSavingTemperature()
}, args...)
}
func changeToComf(_ string, args ...string) {
changeByCallback(func(t fritz.Thermostat) string {
return t.FmtComfortTemperature()
}, args...)
}
func changeBy(val string, args ...string) {
assertMinLen(args, 2, "insufficient input: expected [+ or -] [amount] [devices]")
delta, err := strconv.ParseFloat(val+args[0], 64)
assertNoErr(err, "cannot parse temperature adjustment")
changeByCallback(func(t fritz.Thermostat) string {
cur, err := strconv.ParseFloat(t.FmtGoalTemperature(), 64)
assertNoErr(err, "unable to parse the current temperature goal '%s'", t.FmtGoalTemperature())
return strconv.FormatFloat(cur+delta, 'f', -1, 64)
}, args[1:]...)
}
func changeTo(val string, devs ...string) {
changeByValue(nil, val, devs...)
}
func changeByCallback(supplier func(t fritz.Thermostat) string, names ...string) {
c := homeAutoClient(fritz.Caching(true))
devices, err := c.List()
assertNoErr(err, "cannot list available devices")
for _, name := range names {
device, err := deviceWithName(name, devices.Thermostats())
assertNoErr(err, "unable extract device named '%s'", name)
changeByValue(c, supplier(device.Thermostat), name)
}
}
func deviceWithName(name string, list []fritz.Device) (*fritz.Device, error) {
for _, d := range list {
if d.Name == name {
return &d, nil
}
}
return nil, fmt.Errorf("device with name '%s' not found", name)
}
func changeByValue(c fritz.HomeAuto, val string, names ...string) {
temp, err := parseTemperature(val)
assertNoErr(err, "cannot parse temperature value")
if c == nil {
c = homeAutoClient()
}
err = c.Temp(temp, names...)
assertNoErr(err, "error setting temperature")
}
func parseTemperature(s string) (float64, error) {
if strings.EqualFold(s, "off") {
return 126.5, nil
}
if strings.EqualFold(s, "on") {
return 127.0, nil
}
temp, errorParse := strconv.ParseFloat(s, 64)
return temp, errorParse
}