Got it working!

This commit is contained in:
Daniel Ledda
2020-11-02 23:45:44 +01:00
parent 7b71f1be39
commit 10523274b8
6 changed files with 219 additions and 73 deletions

27
Database.go Normal file
View File

@@ -0,0 +1,27 @@
package main
import (
"database/sql"
"fmt"
)
var ClimateDb *sql.DB
func InitDb() error {
db, err := sql.Open("mysql", "admin:sekna123jk@tcp(127.0.0.1:3306)/climate")
if err != nil {
fmt.Println("error connecting to database")
return err
}
ClimateDb = db
return nil
}
func CloseDb() {
if ClimateDb != nil {
err := ClimateDb.Close()
if err != nil {
fmt.Println("error closing database: " + err.Error())
}
}
}

91
HandlerHelpers.go Normal file
View File

@@ -0,0 +1,91 @@
package main
import (
"fmt"
"net/http"
)
type HandlerFuncWithError = func (http.ResponseWriter, *http.Request) error
type HttpMethod string
const(
HttpGet HttpMethod = "GET"
HttpPost HttpMethod = "POST"
)
type RequestContext struct {
ResponseWriter http.ResponseWriter
Request *http.Request
MethodType HttpMethod
Pattern string
}
type Router struct {
patterns map[string] *PatternRouter
}
type PatternRouter struct {
Get HandlerFuncWithError
Post HandlerFuncWithError
}
func (p *Router) MethodFuncForPattern(methodType HttpMethod, pattern string) (HandlerFuncWithError, error) {
var methodFunc HandlerFuncWithError
switch methodType {
case HttpGet:
methodFunc = p.patterns[pattern].Get
case HttpPost:
methodFunc = p.patterns[pattern].Post
}
if methodFunc == nil {
return nil, fmt.Errorf("method %s not defined on pattern %s", methodType, pattern)
}
return methodFunc, nil
}
func (p *Router) setGet(pattern string, cb HandlerFuncWithError) {
if _, ok := p.patterns[pattern]; ok {
p.patterns[pattern].Get = cb
} else {
p.patterns[pattern] = &PatternRouter{cb, nil}
http.HandleFunc(pattern, getPatternHandler(pattern))
}
}
func (p *Router) setPost(pattern string, cb HandlerFuncWithError) {
if _, ok := p.patterns[pattern]; ok {
p.patterns[pattern].Post = cb
} else {
p.patterns[pattern] = &PatternRouter{nil, cb}
http.HandleFunc(pattern, getPatternHandler(pattern))
}
}
var MainRouter = Router{make(map[string] *PatternRouter)}
func getPatternHandler(pattern string) http.HandlerFunc {
return func (w http.ResponseWriter, r *http.Request) {
cb, err := MainRouter.MethodFuncForPattern(HttpMethod(r.Method), pattern)
if err == nil {
err = cb(w, r)
}
if err != nil {
context := RequestContext{w, r, HttpMethod(r.Method), pattern}
sendInternalError(err, context)
}
}
}
func sendInternalError(err error, context RequestContext) {
errorMessage := "Internal Server Error!"
if DEBUG {
errorMessage += fmt.Sprintf( " Happened during %s request for pattern '%s': %s",
context.MethodType,
context.Pattern,
err.Error())
}
fmt.Println(errorMessage)
http.Error(context.ResponseWriter, errorMessage, 500)
}

41
Snapshot.go Normal file
View File

@@ -0,0 +1,41 @@
package main
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"time"
)
type SnapshotRecord struct {
Id int
Timestamp time.Time
Temp float32
Humidity float32
Co2 float32
}
type SnapshotSubmission struct {
Timestamp float32 `json:"time"`
Temp float32 `json:"temp"`
Humidity float32 `json:"humidity"`
Co2 float32 `json:"co2"`
}
func createSnapshotFromJson(jsonBodyStream io.ReadCloser) (*SnapshotSubmission, error) {
var snapshotSub SnapshotSubmission
body, err := ioutil.ReadAll(jsonBodyStream)
if err != nil {
return nil, fmt.Errorf("error reading body stream: %w", err)
}
err = jsonBodyStream.Close()
if err != nil {
return nil, fmt.Errorf("couldn't close body stream: %w", err)
}
err = json.Unmarshal(body, &snapshotSub)
if err != nil {
return nil, fmt.Errorf("couldn't unmarshal json: %w", err)
}
return &snapshotSub, nil
}

60
climate-server.go Normal file
View File

@@ -0,0 +1,60 @@
package main
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"log"
"net/http"
)
const DEBUG = true
func main() {
err := setup()
defer teardown()
if err == nil {
startServer()
}
}
func setup() error {
err := InitDb()
if err != nil {
return err
}
return nil
}
func teardown() {
CloseDb()
}
func startServer() {
port := "8001"
MainRouter.setGet("/", showCharts)
MainRouter.setPost("/", saveSnapshot)
fmt.Printf("Listening on port %s...\n", port)
log.Fatal(http.ListenAndServe(":" + port, nil))
}
func showCharts(w http.ResponseWriter, r *http.Request) error {
_, err := fmt.Fprint(w, "<h1>Climate Stuff</h1><div>The data will show up here at some stage...</div>")
return err
}
func saveSnapshot(w http.ResponseWriter, r *http.Request) error {
snapshotSub, err := createSnapshotFromJson(r.Body)
if err != nil {
return fmt.Errorf("couldn't create snapshot from JSON: %w", err)
}
_, err = ClimateDb.Query(
fmt.Sprintf("INSERT INTO `snapshots` (`temp`, `humidity`, `co2`, `time`, `id`) VALUES (%v, %v, %v, %v, NULL);",
snapshotSub.Temp,
snapshotSub.Humidity,
snapshotSub.Co2,
snapshotSub.Timestamp))
if err != nil {
return fmt.Errorf("couldn't submit snapshot into the database: %w", err)
}
return nil
}

View File

@@ -1,73 +0,0 @@
package main
import (
"encoding/json"
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt"
"io/ioutil"
"log"
"net/http"
//"net/url"
"time"
)
type SnapshotRecord struct {
Id int
Timestamp time.Time
Temp float32
Humidity float32
Co2 float32
}
type SnapshotSubmission struct {
Timestamp float32 `json:"time"`
Temp float32 `json:"temp"`
Humidity float32 `json:"humidity"`
Co2 float32 `json:"co2"`
}
var climateDb *sql.DB
func setupDb() *sql.DB {
db, err := sql.Open("mysql", "admin:sekna123jk@tcp(127.0.0.1:3306)/climate")
if err != nil {
panic(err.Error())
}
return db
}
func main() {
climateDb = setupDb()
defer climateDb.Close()
http.HandleFunc("/", viewHandler)
fmt.Println("Listening on port 8001...")
log.Fatal(http.ListenAndServe(":8001", nil))
}
func viewHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
_, _ = fmt.Fprint(w, "<h1>Climate Stuff</h1><div>The data will show up here at some stage...</div>")
case "POST":
var snapshotSub SnapshotSubmission
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, "Internal Server Error!", 500)
}
err = json.Unmarshal(body, &snapshotSub)
if err != nil {
http.Error(w, "Internal Server Error!", 500)
}
_, err = climateDb.Query(
fmt.Sprintf("INSERT INTO `snapshots` (`temp`, `humidity`, `co2`, `time`, `id`) VALUES (%v, %v, %v, %v, NULL);",
snapshotSub.Temp,
snapshotSub.Humidity,
snapshotSub.Co2,
snapshotSub.Timestamp))
if err != nil {
http.Error(w, "Internal Server Error!", 500)
}
}
}