-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
122 lines (105 loc) · 3.49 KB
/
main.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
// Package tuya-api is an http server for interacting with the Tuya Cloud API.
//
// It provides two endpoints:
//
// 1. /toggle?id=DEVICE_ID
// Toggles the LED on the device with the given DEVICE_ID.
//
// 2. /set?id=DEVICE_ID&code=CODE&value=VALUE
// Sets the value of the device with the given DEVICE_ID for the given CODE to the given VALUE.
//
// The server listens on port 8015.
package main
import (
"fmt"
"net/http"
"os"
"strconv"
"github.com/gorilla/handlers"
"github.com/joho/godotenv"
"github.com/tuya/tuya-cloud-sdk-go/api/common"
"github.com/tuya/tuya-cloud-sdk-go/api/device"
"github.com/tuya/tuya-cloud-sdk-go/config"
)
// Toggle the LED (`switch_led`) on the device with the given ID.
func toggleLedOnOff(id string) {
dev, _ := device.GetDeviceStatus(id)
for _, v := range dev.Result {
if v.Code == "switch_led" {
cmds := []device.Command{{Code: "switch_led", Value: !v.Value.(bool)}}
device.PostDeviceCommand(id, cmds)
break
}
}
}
// Sets the value of the given code for the given device to the given value and returns the response.
func setDeviceValue(id string, code string, value any) *device.PostDeviceCommandResponse {
cmds := []device.Command{{Code: code, Value: value}}
res, err := device.PostDeviceCommand(id, cmds)
if err != nil {
fmt.Println(err)
panic(err)
}
return res
}
// Returns the value of the given name from the given request's query string. If the value is missing, it writes a 400 response to the given writer and returns an error.
func getRequiredValue(name string, w http.ResponseWriter, r *http.Request) (val string, err error) {
val = r.URL.Query().Get(name)
if val == "" {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("'" + name + "' is required\n"))
err = fmt.Errorf("'" + name + "' is required")
}
return
}
// Returns the values of the given names from the given request's query string. If any of the values are missing, it writes a 400 response to the given writer and returns an error.
func getRequiredValues(w http.ResponseWriter, r *http.Request, names ...string) (vals []string, err error) {
vals = make([]string, len(names))
for i, name := range names {
vals[i], err = getRequiredValue(name, w, r)
if err != nil {
return
}
}
return
}
// Tries to convert the given string to a boolean, integer, or float64. If none of these conversions are successful, it returns the original string.
func someEffortConvert(value string) any {
if b, err := strconv.ParseBool(value); err == nil {
return b
} else if i, err := strconv.Atoi(value); err == nil {
return i
} else if f, err := strconv.ParseFloat(value, 64); err == nil {
return f
} else {
return value
}
}
func main() {
godotenv.Load()
config.SetEnv(common.URLUS, os.Getenv("ACCESS_ID"), os.Getenv("ACCESS_KEY"))
http.HandleFunc("/toggle", func(w http.ResponseWriter, r *http.Request) {
deviceId, err := getRequiredValue("id", w, r)
if err != nil {
return
}
toggleLedOnOff(deviceId)
w.WriteHeader(http.StatusOK)
})
http.HandleFunc("/set", func(w http.ResponseWriter, r *http.Request) {
vals, err := getRequiredValues(w, r, "id", "code", "value")
if err != nil {
return
}
deviceId, code, value := vals[0], vals[1], vals[2]
res := setDeviceValue(deviceId, code, someEffortConvert(value))
if res.Success {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
} else {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(res.Msg))
}
})
http.ListenAndServe(":8015", handlers.LoggingHandler(os.Stdout, http.DefaultServeMux))
}