diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2024-11-26 18:51:15 -0500 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2024-11-26 18:51:15 -0500 |
| commit | a840405f3671bff286ea68f1f6eb0e43975b1a44 (patch) | |
| tree | 92471b84eff8d922e4c7fff3496d3bbf1babb5be /server | |
| parent | d40dee9b7b5327b30e6bcf770dfda14a2e6fed02 (diff) | |
| download | soen422-a840405f3671bff286ea68f1f6eb0e43975b1a44.zip | |
server: chart of humidity vs time
Diffstat (limited to 'server')
| -rw-r--r-- | server/building.go | 6 | ||||
| -rw-r--r-- | server/chart.go | 55 | ||||
| -rw-r--r-- | server/dashboard.go | 8 | ||||
| -rw-r--r-- | server/dashboard.html | 4 | ||||
| -rw-r--r-- | server/record.go | 18 | ||||
| -rw-r--r-- | server/server.go | 1 |
6 files changed, 77 insertions, 15 deletions
diff --git a/server/building.go b/server/building.go index 8772374..e275c65 100644 --- a/server/building.go +++ b/server/building.go @@ -23,10 +23,10 @@ func (b Building) average() (Humidity, bool) { var sum Humidity = 0 nRooms := 0 for room, record := range b { - c := make(chan Humidity) + c := make(chan Entry[Humidity]) record.getRecent <- c - if humidity, ok := <-c; ok { - sum += humidity + if e, ok := <-c; ok { + sum += e.v nRooms++ } else { log.Printf("Warning: no humidity for room '%s'\n", room) diff --git a/server/chart.go b/server/chart.go new file mode 100644 index 0000000..1f20d3c --- /dev/null +++ b/server/chart.go @@ -0,0 +1,55 @@ +package main + +import ( + "log" + "net/http" + "fmt" + "time" + "github.com/wcharczuk/go-chart/v2" +) + +type ChartHandler struct { + building Building +} + +func (h ChartHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + log.Println(r.Method, r.URL) + + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + fmt.Fprintf(w, "invalid method: '%s'", r.Method) + return + } + + var series []chart.Series + for room, record := range h.building { + var x []time.Time + var y []float64 + c := make(chan Entry[Humidity]) + record.get <- c + for e := range c { + x = append(x, e.t) + y = append(y, float64(e.v)) + } + series = append(series, chart.TimeSeries{ + Name: string(room), + XValues: x, + YValues: y, + }) + } + + graph := chart.Chart{ + Background: chart.Style{ + Padding: chart.Box{Top: 20, Left: 20}, + }, + Series: series, + } + graph.Elements = []chart.Renderable{ + chart.Legend(&graph), + } + + w.Header().Set("Content-Type", "image/png") + if err := graph.Render(chart.PNG, w); err != nil { + log.Println(err) + } +} diff --git a/server/dashboard.go b/server/dashboard.go index 48a9423..1dca024 100644 --- a/server/dashboard.go +++ b/server/dashboard.go @@ -65,10 +65,12 @@ func (h DashboardHandler) buildDashboard() Dashboard { rooms := make(map[RoomID]Humidity) for id, record := range h.building { - c := make(chan Humidity) + c := make(chan Entry[Humidity]) record.getRecent <- c - humidity, ok := <-c - if !ok { + var humidity Humidity + if e, ok := <-c; ok { + humidity = e.v + } else { humidity = -1 } rooms[id] = humidity diff --git a/server/dashboard.html b/server/dashboard.html index 23e1d97..50ad682 100644 --- a/server/dashboard.html +++ b/server/dashboard.html @@ -21,6 +21,7 @@ unknown {{- end -}} </p> + <table> <tr><th>Room</th><th>Humidity</th></tr> {{ range $id, $humidity := .Rooms }} @@ -37,5 +38,8 @@ </tr> {{ end }} </table> + + <h4 style="text-align: center;">Humidity per Room vs. Time</h4> + <img src="/chart.png" alt="chart of humidity vs time"/> </body> </html> diff --git a/server/record.go b/server/record.go index c2f38eb..407dcd7 100644 --- a/server/record.go +++ b/server/record.go @@ -6,11 +6,11 @@ import ( type Record[T any] struct { put chan<- T - get chan<- chan T - getRecent chan<- chan T + get chan<- chan Entry[T] + getRecent chan<- chan Entry[T] } -type entry[T any] struct { +type Entry[T any] struct { t time.Time v T } @@ -19,11 +19,11 @@ type entry[T any] struct { // If the capacity is exceeded, old entires will be discarded and new ones kept. func newRecord[T any](capacity int) Record[T] { put := make(chan T) - get := make(chan chan T) - getRecent := make(chan chan T) + get := make(chan chan Entry[T]) + getRecent := make(chan chan Entry[T]) go func() { - entries := make([]entry[T], 0, capacity) + entries := make([]Entry[T], 0, capacity) for { select { @@ -31,7 +31,7 @@ func newRecord[T any](capacity int) Record[T] { if !ok { return } - entries = append(entries, entry[T]{time.Now(), v}) + entries = append(entries, Entry[T]{time.Now(), v}) if len(entries) > capacity { entries = entries[1:] } @@ -40,7 +40,7 @@ func newRecord[T any](capacity int) Record[T] { return } for _, e := range entries { - c <- e.v + c <- e } close(c) case c, ok := <-getRecent: @@ -48,7 +48,7 @@ func newRecord[T any](capacity int) Record[T] { return } if len(entries) > 0 { - c <- entries[len(entries)-1].v + c <- entries[len(entries)-1] } close(c) } diff --git a/server/server.go b/server/server.go index 4ef5151..8cfb1b0 100644 --- a/server/server.go +++ b/server/server.go @@ -33,6 +33,7 @@ func main() { http.Handle("/humidity", HumidityHandler{building}) http.Handle("/target_humidity", TargetHumidityHandler{target}) http.Handle("/duty_cycle", DutyCycleHandler{dutyCycle}) + http.Handle("/chart.png", ChartHandler{building}) fmt.Printf("Listening on %s...\n", addr) log.Fatal(http.ListenAndServe(addr, nil)) |