summaryrefslogtreecommitdiff
path: root/main.go
blob: 6d930b468fa298598b0658726f43b307da357dc3 (plain)
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
package main

import (
	"embed"
	"flag"
	"fmt"
	"log"
	"net/http"
	"text/template"
)

//go:embed simple.css/simple.css templates/index.html
var static embed.FS
var templates *template.Template

func main() {
	configPath := parseFlags()
	c := parseConfig(configPath)

	var err error
	templates, err = template.ParseFS(static, "templates/index.html")
	if err != nil {
		log.Fatal(err)
	}

	http.HandleFunc("/", index(c.Devices))
	http.HandleFunc("/api", api)
	http.Handle("/static/", http.StripPrefix("/static/",
		http.FileServer(http.FS(static))))

	fmt.Printf("Serving at http://%s\n", c.Web.Listen)

	log.Fatal(http.ListenAndServe(c.Web.Listen.String(), nil))
}

// parseFlags() handles command line interface (CLI) flags.
func parseFlags() string {

	var r string

	flag.StringVar(&r, "c", "/etc/webiot/config.json",
		"path to configuration file")
	flag.Parse()

	return r
}

// index() returns a HTTP handler for the index page.
func index(devices DevicesConfig) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		err := templates.Execute(w, devices)
		if err != nil {
			http.Error(w, fmt.Sprint(err), http.StatusInternalServerError)
			return
		}
	}
}

func api(w http.ResponseWriter, r *http.Request) {
	// TODO assert correct HTTP method

	errHost, host := assertSingleParam(r, "host")
	errState, state := assertSingleParam(r, "state")
	if (errHost != nil) || (errState != nil) {
		http.Error(w,
			"Provide exactly one host and one state parameter!", 400)
		return
	}

	err := set(host, state)
	if err != nil {
		http.Error(w, "Could not set WiFi plug.", 500)
	} else {
		fmt.Fprint(w, "ok")
	}
}

// assertSingleParam() returns the value of given URL key and panics if there
// is not exactly one match for this key.
func assertSingleParam(r *http.Request, key string) (error, string) {

	values := r.URL.Query()[key]
	if len(values) != 1 {
		return fmt.Errorf("Provide exactly one '%s' parameter!", key), ""
	}
	return nil, values[0]

}