Got it working!
This commit is contained in:
27
Database.go
Normal file
27
Database.go
Normal 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
91
HandlerHelpers.go
Normal 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
41
Snapshot.go
Normal 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
60
climate-server.go
Normal 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
|
||||||
|
}
|
||||||
73
server.go
73
server.go
@@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user