Initial code generate with swagger codegen
This commit is contained in:
parent
bc405fe6c6
commit
1990634373
4
config.go
Normal file
4
config.go
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
package main
|
||||||
|
var BridgeId = ""
|
||||||
|
var clientSecret = ""
|
||||||
|
var clientId = ""
|
61
dumpjson.go
Normal file
61
dumpjson.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
import "fmt"
|
||||||
|
import "io/ioutil"
|
||||||
|
|
||||||
|
type Status struct {
|
||||||
|
ShutterStatus map[string]int32
|
||||||
|
AirQuality map[string]int32
|
||||||
|
Co2 map[string]int32
|
||||||
|
Temperature map[string]int32
|
||||||
|
Humidity map[string]int32
|
||||||
|
Lux map[string]int32
|
||||||
|
BatteryPercent map[string]int32
|
||||||
|
RfStrength map[string]int32
|
||||||
|
}
|
||||||
|
|
||||||
|
func DumpJSON(state *State, outfile string) {
|
||||||
|
var status = new(Status)
|
||||||
|
status.AirQuality = make(map[string]int32)
|
||||||
|
status.Co2 = make(map[string]int32)
|
||||||
|
status.Temperature = make(map[string]int32)
|
||||||
|
status.Humidity = make(map[string]int32)
|
||||||
|
status.Lux = make(map[string]int32)
|
||||||
|
status.ShutterStatus = make(map[string]int32)
|
||||||
|
status.BatteryPercent = make(map[string]int32)
|
||||||
|
status.RfStrength = make(map[string]int32)
|
||||||
|
|
||||||
|
for _, r := range state.RoomStatus {
|
||||||
|
roomName := state.NameForRoom[r.Id]
|
||||||
|
if r.Temperature != 0 {
|
||||||
|
status.AirQuality[roomName] = r.AirQuality
|
||||||
|
status.Co2[roomName] = r.Co2
|
||||||
|
status.Temperature[roomName] = r.Temperature
|
||||||
|
status.Humidity[roomName] = r.Humidity
|
||||||
|
status.Lux[roomName] = r.Lux
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, m := range state.ModuleStatus {
|
||||||
|
moduleName := state.NameForModule[m.Id]
|
||||||
|
if m.Type_ == "NXO" {
|
||||||
|
status.ShutterStatus[moduleName] = m.TargetPosition
|
||||||
|
} else if m.Type_ == "NXG" {
|
||||||
|
// bridge -- noop
|
||||||
|
} else {
|
||||||
|
status.BatteryPercent[moduleName] = m.BatteryPercent
|
||||||
|
status.RfStrength[moduleName] = m.RfStrength
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonOut, _ := json.Marshal(status)
|
||||||
|
if outfile == "-" {
|
||||||
|
fmt.Println(string(jsonOut))
|
||||||
|
} else {
|
||||||
|
err := ioutil.WriteFile(outfile, jsonOut, 0644)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
73
fetchdata.go
Normal file
73
fetchdata.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
import sw "./go-client"
|
||||||
|
|
||||||
|
type State struct {
|
||||||
|
HomeId string
|
||||||
|
BridgeId string
|
||||||
|
Api *sw.DefaultApiService
|
||||||
|
Auth context.Context
|
||||||
|
NameForRoom map[string]string
|
||||||
|
RoomForName map[string]string
|
||||||
|
RoomForModule map[string]string
|
||||||
|
ModulesForRoom map[string][]string
|
||||||
|
NameForModule map[string]string
|
||||||
|
ModuleForName map[string]string
|
||||||
|
ModuleStatus map[string]sw.ModuleStatus
|
||||||
|
RoomStatus map[string]sw.RoomStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchData(tokenFile string) *State {
|
||||||
|
token := refreshToken(tokenFile)
|
||||||
|
|
||||||
|
var state = &State{
|
||||||
|
Api: sw.NewAPIClient(sw.NewConfiguration()).DefaultApi,
|
||||||
|
BridgeId: BridgeId,
|
||||||
|
Auth: context.WithValue(context.Background(), sw.ContextAccessToken, token.AccessToken),
|
||||||
|
NameForRoom: make(map[string]string),
|
||||||
|
RoomForName: make(map[string]string),
|
||||||
|
RoomForModule: make(map[string]string),
|
||||||
|
ModulesForRoom: make(map[string][]string),
|
||||||
|
NameForModule: make(map[string]string),
|
||||||
|
ModuleForName: make(map[string]string),
|
||||||
|
ModuleStatus: make(map[string]sw.ModuleStatus),
|
||||||
|
RoomStatus: make(map[string]sw.RoomStatus),
|
||||||
|
}
|
||||||
|
|
||||||
|
r, _, err := state.Api.HomesData(state.Auth)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
state.HomeId = r.Body.Homes[0].Id
|
||||||
|
|
||||||
|
for _, r := range r.Body.Homes[0].Rooms {
|
||||||
|
state.NameForRoom[r.Id] = r.Name
|
||||||
|
state.NameForRoom[r.Name] = r.Id
|
||||||
|
for _, m := range r.Modules {
|
||||||
|
state.RoomForModule[m] = r.Id
|
||||||
|
}
|
||||||
|
state.ModulesForRoom[r.Id] = r.Modules
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, m := range r.Body.Homes[0].Modules {
|
||||||
|
state.NameForModule[m.Id] = m.Name
|
||||||
|
state.ModuleForName[m.Name] = m.Id
|
||||||
|
}
|
||||||
|
|
||||||
|
r2, _, err := state.Api.HomeStatus(state.Auth, sw.Body{HomeId: state.HomeId})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, m := range r2.Body.Home.Modules {
|
||||||
|
state.ModuleStatus[m.Id] = m
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range r2.Body.Home.Rooms {
|
||||||
|
state.RoomStatus[r.Id] = r
|
||||||
|
}
|
||||||
|
|
||||||
|
return state
|
||||||
|
}
|
57
main.go
Normal file
57
main.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
import "fmt"
|
||||||
|
import "flag"
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
type arrayFlags []string
|
||||||
|
|
||||||
|
func (i *arrayFlags) String() string {
|
||||||
|
return strings.Join([]string(*i), ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *arrayFlags) Set(value string) error {
|
||||||
|
*i = append(*i, value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if len(os.Args) == 1 {
|
||||||
|
fmt.Println("usage: velux-cli <command> [<args>]")
|
||||||
|
fmt.Println("The most commonly used commands are: ")
|
||||||
|
fmt.Println(" print Shows status")
|
||||||
|
fmt.Println(" dump Writs json into file")
|
||||||
|
fmt.Println(" moveShutters moves shutters")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch os.Args[1] {
|
||||||
|
case "print":
|
||||||
|
printCommand := flag.NewFlagSet("print", flag.ExitOnError)
|
||||||
|
tokenpath := printCommand.String("tokenfile", "/openhab/conf/token.json", "file with access token")
|
||||||
|
printCommand.Parse(os.Args[2:])
|
||||||
|
state := fetchData(*tokenpath)
|
||||||
|
PrintStatus(state)
|
||||||
|
case "dump":
|
||||||
|
dumpCommand := flag.NewFlagSet("print", flag.ExitOnError)
|
||||||
|
tokenpath := dumpCommand.String("tokenfile", "/openhab/conf/token.json", "file with access token")
|
||||||
|
jsonout := dumpCommand.String("outfile", "-", "file writing output to")
|
||||||
|
dumpCommand.Parse(os.Args[2:])
|
||||||
|
state := fetchData(*tokenpath)
|
||||||
|
DumpJSON(state, *jsonout)
|
||||||
|
case "moveShutters":
|
||||||
|
cmd := flag.NewFlagSet("moveShutter", flag.ExitOnError)
|
||||||
|
tokenpath := cmd.String("tokenfile", "/openhab/conf/token.json", "file with access token")
|
||||||
|
position := cmd.Int("pos", 0, "move shutter to position")
|
||||||
|
var shutters arrayFlags
|
||||||
|
cmd.Var(&shutters, "shutters", "which sutters to control")
|
||||||
|
cmd.Parse(os.Args[2:])
|
||||||
|
|
||||||
|
state := fetchData(*tokenpath)
|
||||||
|
Move(state, shutters, int32(*position))
|
||||||
|
default:
|
||||||
|
fmt.Printf("%q is not valid command.\n", os.Args[1])
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
}
|
49
move.go
Normal file
49
move.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
import "encoding/json"
|
||||||
|
import sw "./go-client"
|
||||||
|
|
||||||
|
func Move(state *State, shutters []string, position int32) {
|
||||||
|
fmt.Printf("Moving shutters: %+v to %+v\n", shutters, position)
|
||||||
|
if len(shutters) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var updates []sw.ModulePercentage
|
||||||
|
for _, x := range shutters {
|
||||||
|
m := sw.ModulePercentage{
|
||||||
|
Bridge: state.BridgeId,
|
||||||
|
Id: state.ModuleForName[x],
|
||||||
|
TargetPosition: position,
|
||||||
|
}
|
||||||
|
updates = append(updates, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
param := sw.SetState{
|
||||||
|
Home: &sw.SetStateHome{
|
||||||
|
Id: state.HomeId,
|
||||||
|
Modules: updates,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("> request: %+v\n", param)
|
||||||
|
fmt.Printf("> request: %+v\n", param.Home)
|
||||||
|
fmt.Printf("> request: %+v\n", param.Home.Modules)
|
||||||
|
j, err := json.Marshal(param)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("> request: %+v\n", string(j))
|
||||||
|
|
||||||
|
response, _, err := state.Api.SetState(state.Auth, param)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
j, err = json.Marshal(response)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("> response: %+v\n", string(j))
|
||||||
|
}
|
23
print.go
Normal file
23
print.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func PrintStatus(state *State) {
|
||||||
|
for _, r := range state.RoomStatus {
|
||||||
|
if r.Temperature != 0 {
|
||||||
|
fmt.Printf(
|
||||||
|
"%s (air quality: %d / CO2: %d / Temperature: %d / Humidity: %d / Lux: %d)\n",
|
||||||
|
state.NameForRoom[r.Id], r.AirQuality, r.Co2, r.Temperature/10.0, r.Humidity, r.Lux)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("%s\n", state.NameForRoom[r.Id])
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, m := range state.ModulesForRoom[r.Id] {
|
||||||
|
if state.ModuleStatus[m].Type_ == "NXO" {
|
||||||
|
fmt.Printf(" - %d %s\n", state.ModuleStatus[m].CurrentPosition, state.NameForModule[m])
|
||||||
|
} else {
|
||||||
|
fmt.Printf(" - %s: battery: %d%% rf strength: %d\n", state.NameForModule[m], state.ModuleStatus[m].BatteryPercent, state.ModuleStatus[m].RfStrength)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
109
token.go
Normal file
109
token.go
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
import "fmt"
|
||||||
|
import "log"
|
||||||
|
import "io/ioutil"
|
||||||
|
import "net/http"
|
||||||
|
import "net/url"
|
||||||
|
import "os"
|
||||||
|
import "strings"
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
var myClient = &http.Client{Timeout: 10 * time.Second}
|
||||||
|
|
||||||
|
type Token struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
Scope []string `json:"scope"`
|
||||||
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
ExpireIn int `json:"expire_in"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TokenFile struct {
|
||||||
|
Token *Token `json:"token"`
|
||||||
|
Refreshed time.Time `json:"refreshed"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func readCacheToken(tokenFilePath string) *TokenFile {
|
||||||
|
jsonFile, err := os.Open(tokenFilePath)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
defer jsonFile.Close()
|
||||||
|
|
||||||
|
byteValue, _ := ioutil.ReadAll(jsonFile)
|
||||||
|
var tokenFile TokenFile
|
||||||
|
err = json.Unmarshal(byteValue, &tokenFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &tokenFile
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeCacheToken(tokenFilePath string, r *Token) {
|
||||||
|
file, err := json.MarshalIndent(TokenFile{
|
||||||
|
Token: r,
|
||||||
|
Refreshed: time.Now(),
|
||||||
|
}, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(tokenFilePath, file, 0600)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func doRefresh(refreshToken string) *Token {
|
||||||
|
reqBody := fmt.Sprintf(
|
||||||
|
"grant_type=refresh_token&refresh_token=%s&client_id=%s&client_secret=%s", url.QueryEscape(refreshToken), clientId, clientSecret)
|
||||||
|
|
||||||
|
url := "https://app.velux-active.com/oauth2/token"
|
||||||
|
req, err := http.NewRequest("POST", url, strings.NewReader(reqBody))
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
log.Printf("token refresh: %+v", req)
|
||||||
|
|
||||||
|
resp, err := myClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r := new(Token)
|
||||||
|
err = json.Unmarshal(body, &r)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.AccessToken == "" {
|
||||||
|
log.Panicf("invalid response: %s", body)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func refreshToken(tokenFilePath string) *Token {
|
||||||
|
tokenFile := readCacheToken(tokenFilePath)
|
||||||
|
|
||||||
|
var resultToken *Token
|
||||||
|
|
||||||
|
expireTime := tokenFile.Refreshed.Add(time.Second * time.Duration(tokenFile.Token.ExpireIn))
|
||||||
|
if expireTime.Before(time.Now()) {
|
||||||
|
log.Println("refreshing token")
|
||||||
|
resultToken = doRefresh(tokenFile.Token.RefreshToken)
|
||||||
|
writeCacheToken(tokenFilePath, resultToken)
|
||||||
|
} else {
|
||||||
|
log.Println("skip refreshing token")
|
||||||
|
resultToken = tokenFile.Token
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultToken
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user