added visualisation

This commit is contained in:
Daniel Ledda
2020-11-04 23:50:44 +01:00
parent 42dfd20eb9
commit 4c106fd763
5 changed files with 20933 additions and 27 deletions

20776
Chart.bundle.js Executable file

File diff suppressed because it is too large Load Diff

7
Chart.bundle.min.js vendored Executable file

File diff suppressed because one or more lines are too long

View File

@@ -77,15 +77,5 @@ func getPatternHandler(pattern string) http.HandlerFunc {
}
}
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)
}

115
charts.html Normal file
View File

@@ -0,0 +1,115 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="Chart.bundle.min.js"></script>
</head>
<body>
<div class="chart-container" style="position: relative; height:40vh; width:80vw; margin: auto">
<canvas id="myChart"></canvas>
</div>
<script>
const humidityColor = 'rgb(45,141,45)';
const tempColor = 'rgb(0,134,222)';
const co2Color = 'rgb(194,30,30)';
async function initChart() {
const ctx = document.getElementById('myChart').getContext('2d');
const data = await fetch("http://tortedda.local/climate/data/");
const {humidity, temp, co2} = transformData(await data.json());
const myChart = Chart.Line(ctx, {
data: {
datasets: [{
label: 'Humidity',
data: humidity,
borderColor: humidityColor,
fill: false,
yAxisID: 'y-axis-3',
}, {
label: 'Temperature',
data: temp,
borderColor: tempColor,
fill: false,
yAxisID: 'y-axis-2',
}, {
label: 'Co2 Concentration',
data: co2,
borderColor: co2Color,
fill: false,
yAxisID: 'y-axis-1',
}]
},
options: {
stacked: false,
title: {
display: true,
text: 'Ledda\'s Room Climate',
},
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'second'
}
}],
yAxes: [{
type: 'linear',
display: true,
position: 'right',
id: 'y-axis-1',
ticks: {
fontColor: co2Color,
min: 300,
max: 1200,
},
}, {
type: 'linear',
display: true,
position: 'left',
id: 'y-axis-2',
ticks: {
fontColor: tempColor,
min: 5,
max: 40,
},
gridLines: {
drawOnChartArea: false,
},
}, {
type: 'linear',
display: true,
position: 'left',
id: 'y-axis-3',
ticks: {
fontColor: humidityColor,
min: 0,
max: 100,
},
gridLines: {
drawOnChartArea: false,
},
}],
}
},
});
}
function transformData(json) {
const humidity = [];
const co2 = [];
const temp = [];
for (const snapshot of json.snapshots) {
co2.push({x: snapshot.time, y: snapshot.co2});
temp.push({x: snapshot.time, y: snapshot.temp});
humidity.push({x: snapshot.time, y: snapshot.humidity});
}
return {humidity, co2, temp};
}
initChart();
</script>
</body>
</html>

View File

@@ -3,6 +3,7 @@ package main
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/gorilla/mux"
"log"
"net/http"
)
@@ -31,40 +32,57 @@ func teardown() {
func startServer() {
port := "8001"
MainRouter.setGet("/", showCharts)
MainRouter.setGet("/data/", sendData)
MainRouter.setPost("/", saveSnapshot)
r := mux.NewRouter()
r.HandleFunc("/", showCharts).Methods("GET")
r.HandleFunc("/data", sendData).Methods("GET")
r.HandleFunc("/", saveSnapshot).Methods("POST")
http.Handle("/", r)
fmt.Printf("Listening on port %s...\n", port)
log.Fatal(http.ListenAndServe(":" + port, nil))
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 showCharts(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "charts.html")
}
func sendData(w http.ResponseWriter, r *http.Request) error {
func sendData(w http.ResponseWriter, r *http.Request) {
records, err := getSnapshotRecordsFromDb(50)
if err != nil {
return fmt.Errorf("couldn't read rows from the database: %w", err)
sendInternalError(fmt.Errorf("couldn't read rows from the database: %w", err), w, r)
return
}
json, err := createJsonFromSnapshotRecords(records)
if err != nil {
return fmt.Errorf("couldn't create a json from the records: %w", err)
sendInternalError(fmt.Errorf("couldn't create a json from the records: %w", err), w, r)
return
}
w.Header().Set("Content-Type", "application/json")
_, err = fmt.Fprintf(w, string(json))
return err
if err != nil {
sendInternalError(err, w, r)
return
}
}
func saveSnapshot(w http.ResponseWriter, r *http.Request) error {
func saveSnapshot(w http.ResponseWriter, r *http.Request) {
snapshotSub, err := createSnapshotSubFromJsonBodyStream(r.Body)
if err != nil {
return fmt.Errorf("couldn't create snapshot from JSON: %w", err)
sendInternalError(fmt.Errorf("couldn't create snapshot from JSON: %w", err), w, r)
}
err = writeSnapshotToDb(snapshotSub)
if err != nil {
return fmt.Errorf("couldn't submit snapshot into the database: %w", err)
sendInternalError(fmt.Errorf("couldn't submit snapshot into the database: %w", err), w, r)
}
return nil
}
func sendInternalError(err error, w http.ResponseWriter, r *http.Request) {
errorMessage := "Internal Server Error!"
if DEBUG {
errorMessage += fmt.Sprintf(" Happened during %s request for pattern '%s': %s",
r.Method,
r.URL,
err.Error())
}
fmt.Println(errorMessage)
http.Error(w, errorMessage, 500)
}