Skip to content

Commit 5e6acf8

Browse files
committed
Move api to own package, begin work adding http server functionality
1 parent 790653d commit 5e6acf8

File tree

10 files changed

+203
-48
lines changed

10 files changed

+203
-48
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33

44
#Exclude Built Binaries
55
build/*
6+
.idea/

api.go renamed to api/api.go

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package main
1+
package api
22

33
import (
44
"encoding/json"
@@ -9,33 +9,8 @@ import (
99
"net/url"
1010
)
1111

12-
type thermostatInfo struct {
13-
Name string `json:"name"`
14-
Mode int `json:"mode"`
15-
State int `json:"state"`
16-
Fan int `json:"fan"`
17-
FanState int `json:"fanstate"`
18-
TempUnits int `json:"tempunits"`
19-
Schedule int `json:"schedule"`
20-
SchedulePart int `json:"schedulepart"`
21-
Away int `json:"away"`
22-
Holiday int `json:"holiday"`
23-
Override int `json:"override"`
24-
OverrideTime int `json:"overridetime"`
25-
ForceUnoccupied int `json:"forceunocc"`
26-
SpaceTemp int `json:"spacetemp"`
27-
HeatTemp int `json:"heattemp"`
28-
CoolTemp int `json:"cooltemp"`
29-
CoolTempMin int `json:"cooltempmin"`
30-
CoolTempMax int `json:"cooltempmax"`
31-
HeatTempMin int `json:"heattempmin"`
32-
HeatTempMax int `json:"heattempmax"`
33-
SetPointDelta int `json:"setpointdelta"`
34-
Humidity int `json:"hum"`
35-
AvaliableModes int `json:"avaliablemodes"`
36-
}
37-
38-
func convertThermostatMode(mode string) int {
12+
// ConvertThermostatMode converts the "plain text" mode to the numeric value
13+
func ConvertThermostatMode(mode string) int {
3914
switch mode {
4015
case "off":
4116
return 0
@@ -50,7 +25,8 @@ func convertThermostatMode(mode string) int {
5025
}
5126
}
5227

53-
func convertFanMode(mode string) int {
28+
// ConvertFanMode converts the "plain text" mode to the numeric value
29+
func ConvertFanMode(mode string) int {
5430
switch mode {
5531
case "auto":
5632
return 0
@@ -61,19 +37,21 @@ func convertFanMode(mode string) int {
6137
}
6238
}
6339

64-
func getThermostatInfo(ipaddress string) thermostatInfo {
40+
// GetThermostatInfo pulls the full info from the thermostat
41+
func GetThermostatInfo(ipaddress string) ThermostatInfo {
6542
resp, err := http.Get(fmt.Sprintf("http://%s/query/info", ipaddress))
6643
if err != nil {
6744
log.Fatalln(err)
6845
}
6946
defer resp.Body.Close()
7047
respBytes, _ := ioutil.ReadAll(resp.Body)
71-
var thermostatResponse thermostatInfo
48+
var thermostatResponse ThermostatInfo
7249
json.Unmarshal(respBytes, &thermostatResponse)
7350
return thermostatResponse
7451
}
7552

76-
func setThermostatMode(ipaddress string, mode int, currentInfo thermostatInfo) bool {
53+
// SetThermostatMode sets the thermostat mode
54+
func SetThermostatMode(ipaddress string, mode int, currentInfo ThermostatInfo) bool {
7755
data := url.Values{}
7856
data.Set("heattemp", fmt.Sprintf("%d", currentInfo.HeatTemp))
7957
data.Set("cooltemp", fmt.Sprintf("%d", currentInfo.CoolTemp))
@@ -82,15 +60,17 @@ func setThermostatMode(ipaddress string, mode int, currentInfo thermostatInfo) b
8260
return reqErr == nil
8361
}
8462

85-
func setCoolTemp(ipaddress string, coolTemp int, currentInfo thermostatInfo) bool {
63+
// SetCoolTemp sets the "cool to" temp on the thermostat
64+
func SetCoolTemp(ipaddress string, coolTemp int, currentInfo ThermostatInfo) bool {
8665
data := url.Values{}
8766
data.Set("heattemp", fmt.Sprintf("%d", currentInfo.HeatTemp))
8867
data.Set("cooltemp", fmt.Sprintf("%d", coolTemp))
8968
_, reqErr := http.PostForm(fmt.Sprintf("http://%s/control", ipaddress), url.Values(data))
9069
return reqErr == nil
9170
}
9271

93-
func setFanMode(ipaddress string, fanMode int, currentInfo thermostatInfo) bool {
72+
// SetFanMode sets whether the fan is "auto" or "on"
73+
func SetFanMode(ipaddress string, fanMode int, currentInfo ThermostatInfo) bool {
9474
data := url.Values{}
9575
data.Set("heattemp", fmt.Sprintf("%d", currentInfo.HeatTemp))
9676
data.Set("cooltemp", fmt.Sprintf("%d", currentInfo.CoolTemp))

api/structures.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package api
2+
3+
// ThermostatInfo contains the full info values from the thermostat api
4+
type ThermostatInfo struct {
5+
Name string `json:"name"`
6+
Mode int `json:"mode"`
7+
State int `json:"state"`
8+
Fan int `json:"fan"`
9+
FanState int `json:"fanstate"`
10+
TempUnits int `json:"tempunits"`
11+
Schedule int `json:"schedule"`
12+
SchedulePart int `json:"schedulepart"`
13+
Away int `json:"away"`
14+
Holiday int `json:"holiday"`
15+
Override int `json:"override"`
16+
OverrideTime int `json:"overridetime"`
17+
ForceUnoccupied int `json:"forceunocc"`
18+
SpaceTemp int `json:"spacetemp"`
19+
HeatTemp int `json:"heattemp"`
20+
CoolTemp int `json:"cooltemp"`
21+
CoolTempMin int `json:"cooltempmin"`
22+
CoolTempMax int `json:"cooltempmax"`
23+
HeatTempMin int `json:"heattempmin"`
24+
HeatTempMax int `json:"heattempmax"`
25+
SetPointDelta int `json:"setpointdelta"`
26+
Humidity int `json:"hum"`
27+
AvaliableModes int `json:"avaliablemodes"`
28+
}

go.mod

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,24 @@ module github.com/williampiv/venstar-cli
22

33
go 1.17
44

5-
require github.com/akamensky/argparse v1.3.1
5+
require (
6+
github.com/akamensky/argparse v1.3.1
7+
github.com/gin-gonic/gin v1.7.7
8+
)
9+
10+
require (
11+
github.com/gin-contrib/sse v0.1.0 // indirect
12+
github.com/go-playground/locales v0.13.0 // indirect
13+
github.com/go-playground/universal-translator v0.17.0 // indirect
14+
github.com/go-playground/validator/v10 v10.4.1 // indirect
15+
github.com/golang/protobuf v1.3.3 // indirect
16+
github.com/json-iterator/go v1.1.9 // indirect
17+
github.com/leodido/go-urn v1.2.0 // indirect
18+
github.com/mattn/go-isatty v0.0.12 // indirect
19+
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
20+
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
21+
github.com/ugorji/go/codec v1.1.7 // indirect
22+
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
23+
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 // indirect
24+
gopkg.in/yaml.v2 v2.2.8 // indirect
25+
)

go.sum

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,56 @@
11
github.com/akamensky/argparse v1.3.1 h1:kP6+OyvR0fuBH6UhbE6yh/nskrDEIQgEA1SUXDPjx4g=
22
github.com/akamensky/argparse v1.3.1/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA=
3+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
5+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6+
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
7+
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
8+
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
9+
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
10+
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
11+
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
12+
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
13+
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
14+
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
15+
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
16+
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
17+
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
18+
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
19+
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
20+
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
21+
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
22+
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
23+
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
24+
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
25+
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
26+
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
27+
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
28+
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
29+
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
30+
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
31+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
32+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
33+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
34+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
35+
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
36+
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
37+
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
38+
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
39+
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
40+
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
41+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
42+
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
43+
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
44+
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
45+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
46+
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
47+
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
48+
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
49+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
50+
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
51+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
52+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
53+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
54+
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
55+
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
56+
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

main.go

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,45 @@ package main
22

33
import (
44
"fmt"
5-
"os"
6-
75
"github.com/akamensky/argparse"
6+
"github.com/williampiv/venstar-cli/api"
7+
"github.com/williampiv/venstar-cli/server"
8+
"os"
89
)
910

11+
var commitVersion string
12+
1013
func main() {
1114
parser := argparse.NewParser("venstar-cli", "Access Venstar Thermostat")
1215
ip := parser.String("i", "ip", &argparse.Options{Required: true, Help: "An IP (or hostname) is required to actually access a thermostat"})
1316
setMode := parser.Selector("", "set-mode", []string{"off", "heat", "cool", "auto"}, &argparse.Options{Required: false, Help: "Set the thermostat mode"})
1417
coolTemp := parser.Int("", "set-cool-temp", &argparse.Options{Required: false, Help: "Set the cool-to temperature"})
1518
fanMode := parser.Selector("", "set-fan-mode", []string{"auto", "on"}, &argparse.Options{Required: false, Help: "Set current fan mode to on or auto"})
19+
serverFlag := parser.Flag("", "server", &argparse.Options{Required: false, Help: "run the server"})
1620
err := parser.Parse(os.Args)
1721
if err != nil {
1822
fmt.Print(parser.Usage(err))
23+
os.Exit(1)
1924
}
25+
fmt.Println("Version:", commitVersion)
2026

21-
thermostatData := getThermostatInfo(*ip)
27+
if *serverFlag {
28+
server.Entry(*ip)
29+
os.Exit(0)
30+
} else {
2231

23-
if *setMode != "" {
24-
setThermostatMode(*ip, convertThermostatMode(*setMode), thermostatData)
25-
}
26-
if *coolTemp != 0 {
27-
setCoolTemp(*ip, *coolTemp, thermostatData)
28-
}
29-
if *fanMode != "" {
30-
setFanMode(*ip, convertFanMode(*fanMode), thermostatData)
32+
thermostatData := api.GetThermostatInfo(*ip)
33+
34+
if *setMode != "" {
35+
api.SetThermostatMode(*ip, api.ConvertThermostatMode(*setMode), thermostatData)
36+
}
37+
if *coolTemp != 0 {
38+
api.SetCoolTemp(*ip, *coolTemp, thermostatData)
39+
}
40+
if *fanMode != "" {
41+
api.SetFanMode(*ip, api.ConvertFanMode(*fanMode), thermostatData)
42+
}
43+
printThermostatInfo(thermostatData)
3144
}
32-
printThermostatInfo(thermostatData)
45+
3346
}

server/routes.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package server
2+
3+
import (
4+
"github.com/gin-gonic/gin"
5+
"github.com/williampiv/venstar-cli/api"
6+
"net/http"
7+
)
8+
9+
func initializeRoutes(ip string) {
10+
router.GET("/", showIndexPage)
11+
router.GET("/acOn", turnOnAC(ip))
12+
}
13+
14+
func showIndexPage(c *gin.Context) {
15+
c.HTML(http.StatusOK, "index.html", gin.H{
16+
"title": "Home",
17+
})
18+
}
19+
20+
func turnOnAC(ip string) gin.HandlerFunc {
21+
if ip != "" {
22+
info := api.GetThermostatInfo(ip)
23+
api.SetCoolTemp(ip, 58, info)
24+
api.SetThermostatMode(ip, api.ConvertThermostatMode("cool"), info)
25+
}
26+
return showIndexPage
27+
}

server/server.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package server
2+
3+
import (
4+
"github.com/gin-gonic/gin"
5+
"log"
6+
)
7+
8+
var router *gin.Engine
9+
10+
// Entry is the entrypoint for the server, to run in server mode
11+
func Entry(ip string) {
12+
log.Println("Starting Server Engine...")
13+
router = gin.Default()
14+
router.LoadHTMLGlob("templates/*")
15+
initializeRoutes(ip)
16+
17+
if err := router.Run(); err != nil {
18+
log.Fatalln(err)
19+
}
20+
21+
}

templates/index.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Home</title>
6+
</head>
7+
<body>
8+
<h1>Home!</h1>
9+
</body>
10+
</html>

utils.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ package main
22

33
import (
44
"fmt"
5+
"github.com/williampiv/venstar-cli/api"
56
"reflect"
67
)
78

8-
func printThermostatInfo(info thermostatInfo) {
9+
func printThermostatInfo(info api.ThermostatInfo) {
910
values := reflect.ValueOf(info)
1011
for i := 0; i < values.NumField(); i++ {
1112
fmt.Println(values.Type().Field(i).Name, "\t", values.Field(i))

0 commit comments

Comments
 (0)