/
main.go
147 lines (124 loc) · 4.29 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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package main
import (
"flag"
"github.com/andew42/brightlight/animations"
"github.com/andew42/brightlight/config"
"github.com/andew42/brightlight/controller"
"github.com/andew42/brightlight/framebuffer"
"github.com/andew42/brightlight/servers"
"github.com/andew42/brightlight/stats"
log "github.com/sirupsen/logrus"
"golang.org/x/net/websocket"
"mime"
"net/http"
"os"
// "os"
// "path"
"runtime"
"strings"
)
// LoggedDir Wrap a Dir file system server object to log failures
type LoggedDir struct {
http.Dir
}
// Open Log requests for non existent content
func (d LoggedDir) Open(path string) (http.File, error) {
f, err := d.Dir.Open(path)
if err != nil {
log.WithField("path", path).
Info("requested static HTTP content not found")
}
return f, err
}
// LoggedRedirectingDir Wrap a Dir file system server object to redirect
type LoggedRedirectingDir struct {
LoggedDir
Prefix []string
}
// Open Redirect paths in Prefix slice by remove the entry prefix
// e.g. for entry /buttons path /buttons/index.html -> /index.html
func (d LoggedRedirectingDir) Open(path string) (http.File, error) {
for _, p := range d.Prefix {
if strings.HasPrefix(path, p) {
path = strings.TrimPrefix(path, p)
log.WithField("prefix", p).Info("redirecting")
break
}
}
return d.LoggedDir.Open(path)
}
// Main
func main() {
// Force logrus to use console colouring
var forceColours = flag.Bool("logrusforcecolours", false, "force logrus to use console colouring")
flag.Parse()
if *forceColours {
log.SetFormatter(&log.TextFormatter{ForceColors: true})
}
// Report what are we running on
log.WithFields(
log.Fields{"gover": runtime.Version(), "goos": runtime.GOOS, "goarch": runtime.GOARCH}).
Info("environment")
// Figure out where the content directory is by loading BRIGHTLIGHT
contentBasePath := os.Getenv("BRIGHTLIGHT")
if len(contentBasePath) == 0 {
log.Fatal("BRIGHTLIGHT environment variable not set (web root)")
}
// contentBasePath := "C:/Users/Andrew/GolandProjects/brightlight"
log.WithFields(
log.Fields{"contentBasePath": contentBasePath}).
Info("HTTP content base path")
// Start drivers
controller.StartTeensyDriver()
controller.StartRelayDriver()
renderer := make(chan *framebuffer.FrameBuffer)
framebuffer.StartDriver(renderer)
animations.StartDriver(renderer)
stats.StartDriver()
// Dump out the list of named segments with lengths
//fb := framebuffer.NewFrameBuffer()
//for _, s := range segment.GetAllNamedSegmentNames() {
// seg, _ := segment.GetNamedSegment(s)
// rs := seg.GetSegment(fb)
// fmt.Printf("%s %d\n", s, rs.Len())
//}
// Set up static content serving
mime.AddExtensionType(".manifest", "text/cache-manifest")
// Serve original ui on /ui
fs1 := http.FileServer(LoggedDir{http.Dir(contentBasePath)})
http.Handle("/ui/", fs1)
// Serve new react ui on /
fs2 := http.FileServer(LoggedRedirectingDir{
LoggedDir{http.Dir(contentBasePath + "/ui2/build")},
[]string{"/buttons", "/virtual"}})
// []string{}})
http.Handle("/", fs2)
// Config requires PUT (write) support
http.HandleFunc("/config/", servers.GetConfigHandler(contentBasePath+"/ui"))
http.HandleFunc("/ui-config/", servers.GetConfigHandler(contentBasePath+"/ui2/build"))
// Requests to run zero or more animation (json payload)
http.HandleFunc("/RunAnimations/", servers.RunAnimationsHandler)
// Requests to show a strip length on the room lights
http.HandleFunc("/StripLength/", servers.StripLenHandler)
// Push button state changes over a web socket to keep UIs in sync
http.Handle("/ButtonState", websocket.Handler(servers.ButtonStateHandler))
// Push frame buffer changes over a web socket for virtual framebuffer debugging
http.Handle("/FrameBuffer", websocket.Handler(servers.FrameBufferHandler))
// Push stats info over a web socket
http.Handle("/Stats", websocket.Handler(servers.StatsHandler))
// Request to set server options
http.HandleFunc("/option/", servers.OptionHandler)
// Start web server
ipAndPort, err := config.GetLocalIP()
if err != nil {
log.WithField("err", err).
Fatal("Failed to find an IP address on which to serve content")
}
ipAndPort += ":8080"
log.WithField("address", ipAndPort).
Info("serving old UI at /ui/html and new UI at /")
if err := http.ListenAndServe(ipAndPort, nil); err != nil {
log.Error(err.Error())
}
log.Info("brightlight exited")
}