Przeglądaj źródła

Frontend now has proper responsive charts

Thomas Buck 8 lat temu
rodzic
commit
31863e24ed
5 zmienionych plików z 183 dodań i 80 usunięć
  1. 12
    0
      README.md
  2. 99
    78
      client-script.js
  3. 2
    2
      static.h
  4. 36
    0
      template.html
  5. 34
    0
      test.html

+ 12
- 0
README.md Wyświetl plik

@@ -2,6 +2,18 @@
2 2
 
3 3
 This [started out as a project](https://github.com/g40st/Systemadministration) for the "Systemadministration" course in the Hochschule Ravensburg-Weingarten in the winter of 2016 / 2017.
4 4
 
5
+## Build Steps
6
+
7
+To avoid having to do multiple steps on firmware changes, all static data is compiled into the firmware itself. The included Python 3 script `convert-static.py` should be used to convert the static files (HTML, CSS, JS and the Favicon) into the `static.h` header used by the code.
8
+
9
+When doing changes to any static files, simpy run `./convert-static.py` and then build and upload in the Arduino IDE.
10
+
11
+## Local Webinterface development
12
+
13
+To quickly test changes on the frontend code without having to recompile, use the `test.html` file in a Webbrowser. You need to have an ESP-Weather module running in your network and enter the IP in the html page.
14
+
15
+Of course, any changes to `template.html` should also be done to `test.html`.
16
+
5 17
 ## Dependencies
6 18
 
7 19
 The included Favicon is ['weather' by 'jkeks'](http://www.favicon.cc/?action=icon&file_id=757061).

+ 99
- 78
client-script.js Wyświetl plik

@@ -10,8 +10,6 @@
10 10
 // in return.                                   Thomas Buck & Christian Högerle
11 11
 // ----------------------------------------------------------------------------
12 12
 
13
-var arrSensor = Array(); // Data received from Websockets
14
-
15 13
 // Text Strings. Change these to translate.
16 14
 textAvailableSensors = "Available Sensors";
17 15
 textButtonNext = "Continue";
@@ -35,26 +33,55 @@ preDefinedColors = Array(
35 33
 var actTime = new Date();
36 34
 actTime = actTime.getHours() + ":" + (actTime.getMinutes() < 10 ? '0':'') + actTime.getMinutes();
37 35
 
36
+var arrSensor = Array(); // Data received from Websockets
37
+var currentState = "initial"; // "initial", "main", "1", "2", ...
38
+
38 39
 // Draw initial view when the page has been loaded
39
-$(document).ready(initialView);
40
+$(document).ready(resizeAndRedraw);
41
+
42
+// Match graph canvases to their parent containers on resize
43
+$(window).on('resize', resizeAndRedraw, false);
44
+
45
+// Redraw current graph view, used for resizing
46
+function redraw(animate) {
47
+    if (currentState === "initial") {
48
+        initialView();
49
+    } else if (currentState === "main") {
50
+        generateView(arrSensor, animate);
51
+    } else {
52
+        var n = Math.floor(Number(currentState));
53
+        if ((String(n) === currentState) && (n >= 0)) {
54
+            generateGraph(false, arrSensor[(currentState - 1)], animate);
55
+        } else {
56
+            console.log("Invalid state: " + currentState);
57
+        }
58
+    }
59
+}
60
+
61
+function resize() {
62
+    $("canvas").each(function(i, el) {
63
+        $(el).attr({
64
+            "width":$(el).parent().width(),
65
+            "height":$(el).parent().outerHeight()
66
+        });
67
+    });
68
+}
69
+
70
+function resizeAndRedraw(animate) {
71
+    resize();
72
+    redraw(animate);
73
+}
40 74
 
41 75
 function initialView() {
42
-    $('#contentDiv').empty();
43
-    $('#contentDiv').append(`<div class="col-sm-12 col-md-12 col-lg-12">
44
-        <div class="panel panel-primary">
45
-            <div class="panel-heading" id="listSensorsHeading">
46
-                ` + textAvailableSensors + ` (0/0)
47
-            </div>
48
-            <div class="panel-body">
49
-                <ul class="list-group" id="listSensors"></ul>
50
-                <div id="alertDiv"></div>
51
-                <button class="btn btn-primary" disabled="" id="btnSubmit">
52
-                    ` + textButtonNext + `
53
-                </button>
54
-            </div>
55
-        </div>
56
-    </div>`);
76
+    // Show first page and hide the graphs
77
+    $('#startDiv').show();
78
+    $('#dataDiv').hide();
57 79
 
80
+    // Reset the button text
81
+    $('#btnSubmit').empty();
82
+    $('#btnSubmit').html(textButtonNext);
83
+
84
+    // Reset heading with number of clients
58 85
     $('#listSensorsHeading').empty();
59 86
     $('#listSensorsHeading').html(textAvailableSensors + " (0/" + clients.length + ")");
60 87
 
@@ -66,8 +93,8 @@ function initialView() {
66 93
 
67 94
     // Button to continue to graph view
68 95
     $("#btnSubmit").click(function(event) {
69
-        $('#contentDiv').empty();
70
-        generateView(arrSensor);
96
+        currentState = "main";
97
+        resizeAndRedraw(true);
71 98
     });
72 99
 }
73 100
 
@@ -107,54 +134,44 @@ function webSocket(wsUri, wsPort, count, clientsCount) {
107 134
                                     + '</strong><br>' + errorMessage
108 135
                                     + wsUri + '<br></div>');
109 136
         }
110
-        console.log(evt.data);
137
+        console.log("WebSocket Error: " + evt.data);
111 138
     };
112 139
 }
113 140
 
114
-function generateView(arrSensor) {
115
-    $('#contentDiv').append(`<div class="col-sm-12 col-md-12 col-lg-12">
116
-                                <div class="panel panel-primary">
117
-                                    <ul class="nav nav-pills">
118
-                                        <li class="active"><a class="navtab" data-toggle="tab" href="#home">` + homeTabName + `</a></li>
119
-                                    </ul>
120
-                                    <div class="panel-body">
121
-                                        <div id="contentPanel">
122
-                                        </div>
123
-                                    </div>
124
-                                </div>
125
-                            </div>`);
141
+function generateView(arrSensor, animation) {
142
+    // Hide first page, show graph page
143
+    $('#startDiv').hide();
144
+    $('#dataDiv').show();
145
+
146
+    // Add home tab
147
+    $('.nav-pills').empty();
148
+    $('.nav-pills').append('<li class="active"><a id="homebut" class="navtab" data-toggle="tab" href="#home">' + homeTabName + '</a></li>');
126 149
 
150
+    // Add tabs for all sensors
127 151
     jQuery.each(arrSensor, function(index, sensor) {
128
-        $('.nav-pills').append('<li><a class="navtab" data-toggle="tab" href="#' + sensor.id + '">' + sensorTabName + ' ' + sensor.id + '</a></li>');
152
+        $('.nav-pills').append('<li><a id="sensbut" class="navtab" data-toggle="tab" href="#' + sensor.id + '">' + sensorTabName + ' ' + sensor.id + '</a></li>');
129 153
     });
130 154
 
131 155
     // flag for combined plot -> true
132
-    generateGraph(true, arrSensor);
156
+    generateGraph(true, arrSensor, animation);
133 157
 
134
-    $(".navtab").click(function(event) {
135
-        $('#contentPanel').empty();
136
-        if(event.target.text == homeTabName) {
137
-            // flag for combined plot -> true
138
-            generateGraph(true, arrSensor);
139
-        } else {
140
-            generateGraph(false, arrSensor[(event.target.text.split(" ")[1] - 1)]);
141
-        }
158
+    // Handler for "Home" button, drawing combined graph
159
+    $("#homebut").click(function(event) {
160
+        // flag for combined plot -> true
161
+        generateGraph(true, arrSensor, true);
162
+        currentState = "main";
163
+    });
164
+
165
+    // Handler for single sensor buttons
166
+    $("#sensbut").click(function(event) {
167
+        generateGraph(false, arrSensor[(event.target.text.split(" ")[1] - 1)], true);
168
+        currentState = event.target.text.split(" ")[1];
142 169
     });
143 170
 }
144 171
 
145
-function generateGraph(flag, sensor) {
146
-    $('#contentPanel').append(`<div class="row">
147
-                                <div class="col-sm-12 col-md-12 col-lg-6">
148
-                                    <div id="temperatureDiv" class="embed-responsive embed-responsive-4by3">
149
-                                        <canvas id="temperatureChart"></canvas>
150
-                                    </div>
151
-                                </div>
152
-                                <div class="col-sm-12 col-md-12 col-lg-6">
153
-                                    <div id="humidityDiv" class="embed-responsive embed-responsive-4by3">
154
-                                        <canvas id="humidityChart"></canvas>
155
-                                    </div>
156
-                                </div>
157
-                            </div>`);
172
+function generateGraph(flag, sensor, anim) {
173
+    resize();
174
+
158 175
     if (flag) {
159 176
         // one plot for all sensors
160 177
         var length = 0;
@@ -226,10 +243,30 @@ function generateGraph(flag, sensor) {
226 243
     var tempCtx = $('#temperatureChart');
227 244
     var humCtx = $('#humidityChart');
228 245
 
229
-    //tempCtx.attr('width', $('#temperatureDiv').width());
230
-    //tempCtx.attr('height', $('#temperatureDiv').height());
231
-    //humCtx.attr('width', $('#humidityDiv').width());
232
-    //humCtx.attr('height', $('#humidityDiv').height());
246
+    var tempOptions = {
247
+        title: {
248
+            display: true,
249
+            text: temperatureHeading
250
+        },
251
+        responsive: true,
252
+        maintainAspectRatio: true,
253
+        scaleOverride: true,
254
+    };
255
+
256
+    var humOptions = {
257
+        title: {
258
+            display: true,
259
+            text: humidityHeading
260
+        },
261
+        responsive: true,
262
+        maintainAspectRatio: true,
263
+        scaleOverride: true,
264
+    };
265
+
266
+    if (!anim) {
267
+        tempOptions.animation = false;
268
+        humOptions.animation = false;
269
+    }
233 270
 
234 271
     var tempChart = new Chart(tempCtx, {
235 272
         type: 'line',
@@ -237,15 +274,7 @@ function generateGraph(flag, sensor) {
237 274
             labels: labels,
238 275
             datasets: dataTemperature,
239 276
         },
240
-        options: {
241
-            title: {
242
-                display: true,
243
-                text: temperatureHeading
244
-            },
245
-            responsive: true,
246
-            maintainAspectRatio: true,
247
-            scaleOverride: true
248
-        }
277
+        options: tempOptions
249 278
     });
250 279
 
251 280
     var humCharts = new Chart(humCtx, {
@@ -254,15 +283,7 @@ function generateGraph(flag, sensor) {
254 283
             labels: labels,
255 284
             datasets: dataHumidity,
256 285
         },
257
-        options: {
258
-            title: {
259
-                display: true,
260
-                text: humidityHeading
261
-            },
262
-            responsive: true,
263
-            maintainAspectRatio: true,
264
-            scaleOverride: true
265
-        }
286
+        options: humOptions
266 287
     });
267 288
 }
268 289
 

+ 2
- 2
static.h
Plik diff jest za duży
Wyświetl plik


+ 36
- 0
template.html Wyświetl plik

@@ -37,6 +37,42 @@
37 37
             <div class="page-header">
38 38
                 <h2>ESP-Weather <small>v2</small></h2>
39 39
             </div>
40
+            <div class="row" id="contentDiv">
41
+                <div id="startDiv" class="col-sm-12 col-md-12 col-lg-12" style="display: none;">
42
+                    <div class="panel panel-primary">
43
+                        <div class="panel-heading" id="listSensorsHeading">
44
+                        </div>
45
+                        <div class="panel-body">
46
+                            <ul class="list-group" id="listSensors"></ul>
47
+                            <div id="alertDiv"></div>
48
+                            <button class="btn btn-primary" disabled="" id="btnSubmit">
49
+                            </button>
50
+                        </div>
51
+                    </div>
52
+                </div>
53
+                <div id="dataDiv" class="col-sm-12 col-md-12 col-lg-12" style="display: none;">
54
+                    <div class="panel panel-primary">
55
+                        <ul class="nav nav-pills">
56
+                        </ul>
57
+                        <div class="panel-body">
58
+                            <div id="contentPanel">
59
+                                <div class="row">
60
+                                    <div class="col-sm-12 col-md-12 col-lg-6">
61
+                                        <div id="temperatureDiv" class="embed-responsive embed-responsive-4by3">
62
+                                            <canvas id="temperatureChart"></canvas>
63
+                                        </div>
64
+                                    </div>
65
+                                    <div class="col-sm-12 col-md-12 col-lg-6">
66
+                                        <div id="humidityDiv" class="embed-responsive embed-responsive-4by3">
67
+                                            <canvas id="humidityChart"></canvas>
68
+                                        </div>
69
+                                    </div>
70
+                                </div>
71
+                            </div>
72
+                        </div>
73
+                    </div>
74
+                </div>
75
+            </div>
40 76
         </div>
41 77
         <div class="footer">
42 78
             <div class="container">

+ 34
- 0
test.html Wyświetl plik

@@ -38,6 +38,40 @@
38 38
                 <h2>ESP-Weather <small>v2</small></h2>
39 39
             </div>
40 40
             <div class="row" id="contentDiv">
41
+                <div id="startDiv" class="col-sm-12 col-md-12 col-lg-12" style="display: none;">
42
+                    <div class="panel panel-primary">
43
+                        <div class="panel-heading" id="listSensorsHeading">
44
+                        </div>
45
+                        <div class="panel-body">
46
+                            <ul class="list-group" id="listSensors"></ul>
47
+                            <div id="alertDiv"></div>
48
+                            <button class="btn btn-primary" disabled="" id="btnSubmit">
49
+                            </button>
50
+                        </div>
51
+                    </div>
52
+                </div>
53
+                <div id="dataDiv" class="col-sm-12 col-md-12 col-lg-12" style="display: none;">
54
+                    <div class="panel panel-primary">
55
+                        <ul class="nav nav-pills">
56
+                        </ul>
57
+                        <div class="panel-body">
58
+                            <div id="contentPanel">
59
+                                <div class="row">
60
+                                    <div class="col-sm-12 col-md-12 col-lg-6">
61
+                                        <div id="temperatureDiv" class="embed-responsive embed-responsive-4by3">
62
+                                            <canvas id="temperatureChart"></canvas>
63
+                                        </div>
64
+                                    </div>
65
+                                    <div class="col-sm-12 col-md-12 col-lg-6">
66
+                                        <div id="humidityDiv" class="embed-responsive embed-responsive-4by3">
67
+                                            <canvas id="humidityChart"></canvas>
68
+                                        </div>
69
+                                    </div>
70
+                                </div>
71
+                            </div>
72
+                        </div>
73
+                    </div>
74
+                </div>
41 75
             </div>
42 76
         </div>
43 77
         <div class="footer">

Ładowanie…
Anuluj
Zapisz