From 34831bbc59b0cb62ec837e1791457cf3bd4574ce Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Mon, 4 Nov 2024 10:34:37 -0500 Subject: server: humidity record for each room --- .gitignore | 1 - Makefile | 10 ------- record.go | 60 ------------------------------------------ server.go | 67 ----------------------------------------------- server/Makefile | 10 +++++++ server/record.go | 60 ++++++++++++++++++++++++++++++++++++++++++ server/server.go | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 150 insertions(+), 138 deletions(-) delete mode 100644 Makefile delete mode 100644 record.go delete mode 100644 server.go create mode 100644 server/Makefile create mode 100644 server/record.go create mode 100644 server/server.go diff --git a/.gitignore b/.gitignore index 8dd0011..7bf61ab 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ *.pdf -server *.bak *.png *.aux diff --git a/Makefile b/Makefile deleted file mode 100644 index 8954492..0000000 --- a/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -SRC = server.go record.go - -server: ${SRC} - go build $^ - -fmt: - gofmt -l -s -w ${SRC} - -clean: - rm -f server diff --git a/record.go b/record.go deleted file mode 100644 index 9051146..0000000 --- a/record.go +++ /dev/null @@ -1,60 +0,0 @@ -package main - -import ( - "time" -) - -type Record[T any] struct { - put chan<- T - get chan<- chan T - getRecent chan<- chan T -} - -type entry[T any] struct { - t time.Time - v T -} - -func newRecord[T any]() Record[T] { - put := make(chan T) - get := make(chan chan T) - getRecent := make(chan chan T) - - go func() { - var entries []entry[T] - - for { - select { - case v, ok := <-put: - if !ok { - return - } - entries = append(entries, entry[T]{time.Now(), v}) - case c, ok := <-get: - if !ok { - return - } - for _, e := range entries { - c <- e.v - } - close(c) - case c, ok := <-getRecent: - if !ok { - return - } - if len(entries) > 0 { - c <- entries[len(entries)-1].v - } - close(c) - } - } - }() - - return Record[T]{put, get, getRecent} -} - -func (l Record[T]) Close() { - close(l.put) - close(l.get) - close(l.getRecent) -} diff --git a/server.go b/server.go deleted file mode 100644 index b4caecb..0000000 --- a/server.go +++ /dev/null @@ -1,67 +0,0 @@ -package main - -import ( - "fmt" - "log" - "net/http" - "strconv" -) - -const addr = ":9090" - -type HumidityHandler struct { - humidity Record[float32] -} - -func newHumidityHandler() HumidityHandler { - return HumidityHandler{newRecord[float32]()} -} - -func (h HumidityHandler) Close() { - h.humidity.Close() -} - -func (h HumidityHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - log.Println(r.Method, r.URL) - switch r.Method { - case http.MethodGet: - h.get(w, r) - case http.MethodPost: - h.post(w, r) - default: - w.WriteHeader(http.StatusMethodNotAllowed) - fmt.Fprintf(w, "invalid method: '%s'", r.Method) - } -} - -func (h HumidityHandler) get(w http.ResponseWriter, r *http.Request) { - c := make(chan float32) - h.humidity.getRecent <- c - humidity, ok := <-c - if !ok { - w.WriteHeader(http.StatusGone) - fmt.Fprintf(w, "no humidity data stored on server") - return - } - fmt.Fprintf(w, "%.2f", humidity) -} - -func (h HumidityHandler) post(w http.ResponseWriter, r *http.Request) { - query := r.URL.RawQuery - humidity, err := strconv.ParseFloat(query, 32) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - fmt.Fprintf(w, "invalid query string: '%s'", query) - return - } - h.humidity.put <- float32(humidity) -} - -func main() { - humidityHandler := newHumidityHandler() - defer humidityHandler.Close() - - http.Handle("/humidity", humidityHandler) - fmt.Printf("Listening on %s...\n", addr) - log.Fatal(http.ListenAndServe(addr, nil)) -} diff --git a/server/Makefile b/server/Makefile new file mode 100644 index 0000000..8954492 --- /dev/null +++ b/server/Makefile @@ -0,0 +1,10 @@ +SRC = server.go record.go + +server: ${SRC} + go build $^ + +fmt: + gofmt -l -s -w ${SRC} + +clean: + rm -f server diff --git a/server/record.go b/server/record.go new file mode 100644 index 0000000..9051146 --- /dev/null +++ b/server/record.go @@ -0,0 +1,60 @@ +package main + +import ( + "time" +) + +type Record[T any] struct { + put chan<- T + get chan<- chan T + getRecent chan<- chan T +} + +type entry[T any] struct { + t time.Time + v T +} + +func newRecord[T any]() Record[T] { + put := make(chan T) + get := make(chan chan T) + getRecent := make(chan chan T) + + go func() { + var entries []entry[T] + + for { + select { + case v, ok := <-put: + if !ok { + return + } + entries = append(entries, entry[T]{time.Now(), v}) + case c, ok := <-get: + if !ok { + return + } + for _, e := range entries { + c <- e.v + } + close(c) + case c, ok := <-getRecent: + if !ok { + return + } + if len(entries) > 0 { + c <- entries[len(entries)-1].v + } + close(c) + } + } + }() + + return Record[T]{put, get, getRecent} +} + +func (l Record[T]) Close() { + close(l.put) + close(l.get) + close(l.getRecent) +} diff --git a/server/server.go b/server/server.go new file mode 100644 index 0000000..2795890 --- /dev/null +++ b/server/server.go @@ -0,0 +1,80 @@ +package main + +import ( + "fmt" + "log" + "net/http" + "strconv" +) + +const addr = ":9090" +var rooms = []RoomID { + ",4AL[+V*:*k*n{7vL{}/d=K#Mo*y*^.@", + "Jq!+