gpio-webhook-server/cmd/smartswitch-server/main.go

105 lines
2.3 KiB
Go

package main
import (
"encoding/json"
"io/ioutil"
"log"
"net/http"
"github.com/spf13/viper"
"gopkg.in/yaml.v2"
)
type webhook struct {
Name string
Path string
NumSwitches int `yaml:"num_switches"`
MomentarySwitches []int `yaml:"momentary_switches"`
SwitchStates []int `json:switch_states`
}
func debug(msg string, args ...interface{}) {
if viper.GetBool("Debug") {
log.Printf(msg, args...)
}
}
func initWebhooks(filename string) {
bytes, err := ioutil.ReadFile(filename)
if err != nil {
log.Panicf("Couldn't read config file: %s", err)
}
var hooks []webhook
err = yaml.Unmarshal(bytes, &hooks)
if err != nil {
log.Panicf("Couldn't parse webhook file: %v", err)
}
debug("Webhook definitions:")
debug("%v", hooks)
for _, v := range hooks {
v.SwitchStates = make([]int, v.NumSwitches)
http.HandleFunc("/"+v.Path, makeWebhookHandler(v))
}
}
func runServer() {
log.Printf("Starting server on port %s", viper.GetString("ListenPort"))
log.Fatal(http.ListenAndServe(":"+viper.GetString("ListenPort"), nil))
}
func makeWebhookHandler(hook webhook) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
webhookRead(hook, w, r)
} else if r.Method == "POST" {
webhookWrite(hook, w, r)
}
}
}
func webhookRead(hook webhook, w http.ResponseWriter, r *http.Request) {
err := json.NewEncoder(w).Encode(hook.SwitchStates)
if err != nil {
log.Printf("Failed to send response: %v", err)
return
}
// momentary switches have been read, so make sure they're 0
// next time
for _, i := range hook.MomentarySwitches {
hook.SwitchStates[i] = 0
}
}
func webhookWrite(hook webhook, w http.ResponseWriter, r *http.Request) {
err := json.NewDecoder(r.Body).Decode(&hook.SwitchStates)
if err != nil {
log.Printf("Failed to parse json for '%s': %v", hook.Name, err)
http.Error(w, "Failed to parse json", http.StatusBadRequest)
return
}
}
func main() {
// read environment config
viper.BindEnv("Debug", "DEBUG")
viper.BindEnv("WebhookFile", "WEBHOOK_CONFIG_FILE")
viper.BindEnv("ListenPort", "PORT")
viper.SetDefault("ListenPort", "7200")
viper.SetDefault("WebhookFile", "./webhooks.yaml")
viper.SetDefault("Debug", false)
// read webhook config
initWebhooks(viper.GetString("WebhookFile"))
// serve app
runServer()
}