Skip to content

Commit 54267c3

Browse files
committed
Update: Finalise all generic_resource_modelling
This commit updates and finalises all dashboard files. These include changes in various files like serialisers, dashboard and views and urls. Signed-off-by: Akarshan Kapoor <data.akarshan@icloud.com>
1 parent 729d77c commit 54267c3

14 files changed

+1368
-282
lines changed

server/django/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ djangorestframework==3.15.2
55
whitenoise==6.7.0
66
celery[redis]==5.4.0
77
gevent==24.2.1
8+
numpy==2.1.1
89
python-dateutil==2.9.0
910

1011
# Generation of Entity-Relationship Diagrams

server/django/sensordata/serializers/generic_resource_serializer.py

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#
2+
# Copyright (c) 2024 Jonas Remmert
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
7+
from rest_framework import serializers
8+
from ..models import Endpoint, Resource, Firmware, EndpointOperation, FirmwareUpdate, ResourceType
9+
10+
class EndpointSerializer(serializers.ModelSerializer):
11+
class Meta:
12+
model = Endpoint
13+
fields = ['endpoint', 'registered']
14+
15+
class ResourceTypeSerializer(serializers.ModelSerializer):
16+
class Meta:
17+
model = ResourceType
18+
fields = ['object_id', 'resource_id', 'name', 'data_type']
19+
20+
class GenericResourceSerializer(serializers.ModelSerializer):
21+
resource_type = ResourceTypeSerializer(read_only=True)
22+
23+
class Meta:
24+
model = Resource
25+
fields = ['id', 'endpoint', 'resource_type', 'int_value', 'float_value', 'str_value', 'timestamp_created']
26+
27+
class FirmwareSerializer(serializers.ModelSerializer):
28+
class Meta:
29+
model = Firmware
30+
fields = ['id', 'version', 'created_at', 'binary']
31+
32+
class EndpointOperationSerializer(serializers.ModelSerializer):
33+
class Meta:
34+
model = EndpointOperation
35+
fields = ['id', 'resource', 'operation_type', 'status', 'timestamp_created', 'last_attempt']
36+
37+
class FirmwareUpdateSerializer(serializers.ModelSerializer):
38+
firmware = FirmwareSerializer(read_only=True)
39+
40+
class Meta:
41+
model = FirmwareUpdate
42+
fields = ['id', 'endpoint', 'firmware', 'state', 'result', 'timestamp_created', 'timestamp_updated']
43+
44+
class ResourceDataSerializer(serializers.Serializer):
45+
KIND_CHOICES = [
46+
'singleResource',
47+
'multiResource',
48+
]
49+
kind = serializers.ChoiceField(choices=KIND_CHOICES)
50+
id = serializers.IntegerField(help_text="Resource ID")
51+
type = serializers.ChoiceField(choices=ResourceType.TYPE_CHOICES)
52+
value = serializers.CharField(max_length=255, required=False, allow_blank=True)
53+
values = serializers.DictField(child=serializers.CharField(max_length=255), required=False, allow_empty=True)
Lines changed: 221 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,223 @@
1-
{% extends 'base.html' %}
1+
{% extends "base.html" %}
2+
{% load static %}
3+
24
{% block content %}
3-
<h1>Admin Dashboard</h1>
4-
<table class="table">
5-
<thead>
6-
<tr>
7-
<th>Endpoint</th>
8-
</tr>
9-
</thead>
10-
<tbody>
11-
{% for device in devices %}
12-
<tr>
13-
<td>{{ device.endpoint }}</td>
14-
</tr>
15-
{% endfor %}
16-
</tbody>
17-
</table>
5+
<div class="row">
6+
<div class="col-lg-3 col-6">
7+
<div class="small-box bg-info">
8+
<div class="inner">
9+
<h3>{{ total_devices }}</h3>
10+
<p>Total Devices</p>
11+
</div>
12+
<div class="icon">
13+
<i class="fas fa-microchip"></i>
14+
</div>
15+
</div>
16+
</div>
17+
18+
<div class="col-lg-3 col-6">
19+
<div class="small-box bg-warning">
20+
<div class="inner">
21+
<h3>{{ firmware_updates_in_progress }}</h3>
22+
<p>Firmware Updates</p>
23+
</div>
24+
<div class="icon">
25+
<i class="fas fa-download"></i>
26+
</div>
27+
</div>
28+
</div>
29+
30+
<div class="col-lg-3 col-6">
31+
<!-- small box for Pending Communications -->
32+
<div class="small-box bg-success">
33+
<div class="inner">
34+
<h3>{{ pending_communications_count }}</h3>
35+
<p>Pending Comms</p>
36+
37+
</div>
38+
<div class="icon">
39+
<i class="fas fa-exchange-alt"></i>
40+
</div>
41+
</div>
42+
</div>
43+
44+
</div>
45+
46+
<div class="row">
47+
<div class="col-md-6">
48+
<div class="card">
49+
<div class="card-header">
50+
<h3 class="card-title">Registered vs Unregistered Devices</h3>
51+
</div>
52+
<div class="card-body">
53+
<canvas id="deviceStatusChart"></canvas>
54+
</div>
55+
</div>
56+
</div>
57+
58+
<div class="col-md-6">
59+
<div class="card">
60+
<div class="card-header">
61+
<h3 class="card-title">Total Added Values Over Time</h3>
62+
<div class="card-tools">
63+
<select id="timeRangeSelector" class="form-control">
64+
{% if time_range == 'week' %}
65+
<option value="week" selected>Last Week</option>
66+
{% else %}
67+
<option value="week">Last Week</option>
68+
{% endif %}
69+
70+
{% if time_range == 'month' %}
71+
<option value="month" selected>Last Month</option>
72+
{% else %}
73+
<option value="month">Last Month</option>
74+
{% endif %}
75+
76+
{% if time_range == 'year' %}
77+
<option value="year" selected>Last Year</option>
78+
{% else %}
79+
<option value="year">Last Year</option>
80+
{% endif %}
81+
</select>
82+
</div>
83+
</div>
84+
<div class="card-body">
85+
<canvas id="addedValuesChart"></canvas>
86+
</div>
87+
</div>
88+
</div>
89+
</div>
90+
91+
<div class="row">
92+
<div class="col-md-12">
93+
<div class="card">
94+
<div class="card-header">
95+
<h3 class="card-title">Event Visualization</h3>
96+
<div class="card-tools">
97+
<select id="eventTypeSelector" class="form-control">
98+
<option value="all" {% if selected_event_type == 'all' %}selected{% endif %}>All Events</option>
99+
{% for event_type in event_types %}
100+
<option value="{{ event_type }}" {% if selected_event_type == event_type %}selected{% endif %}>
101+
{{ event_type }}
102+
</option>
103+
{% endfor %}
104+
</select>
105+
106+
<select id="eventTimeRangeSelector" class="form-control">
107+
{% if event_time_range == 'week' %}
108+
<option value="week" selected>Last Week</option>
109+
{% else %}
110+
<option value="week">Last Week</option>
111+
{% endif %}
112+
113+
{% if event_time_range == 'month' %}
114+
<option value="month" selected>Last Month</option>
115+
{% else %}
116+
<option value="month">Last Month</option>
117+
{% endif %}
118+
119+
{% if event_time_range == 'year' %}
120+
<option value="year" selected>Last Year</option>
121+
{% else %}
122+
<option value="year">Last Year</option>
123+
{% endif %}
124+
</select>
125+
</div>
126+
</div>
127+
<div class="card-body">
128+
<canvas id="eventChart"></canvas>
129+
</div>
130+
</div>
131+
</div>
132+
</div>
18133
{% endblock %}
134+
135+
{% block extra_js %}
136+
<script>
137+
document.addEventListener('DOMContentLoaded', function () {
138+
var ctx = document.getElementById('deviceStatusChart').getContext('2d');
139+
var deviceStatusChart = new Chart(ctx, {
140+
type: 'bar',
141+
data: {
142+
labels: ['Registered', 'Unregistered'],
143+
datasets: [{
144+
label: 'Number of Devices',
145+
data: [{{ registered_devices }}, {{ unregistered_devices }}],
146+
backgroundColor: [
147+
'rgba(75, 192, 192, 0.2)',
148+
'rgba(255, 99, 132, 0.2)'
149+
],
150+
borderColor: [
151+
'rgba(75, 192, 192, 1)',
152+
'rgba(255, 99, 132, 1)'
153+
],
154+
borderWidth: 1
155+
}]
156+
},
157+
options: {
158+
scales: {
159+
y: {
160+
beginAtZero: true
161+
}
162+
}
163+
}
164+
});
165+
166+
var addedValuesCtx = document.getElementById('addedValuesChart').getContext('2d');
167+
var addedValuesChart = new Chart(addedValuesCtx, {
168+
type: 'line',
169+
data: {
170+
labels: {{ added_values_dates| safe }},
171+
datasets: [{
172+
label: 'Total Added Values',
173+
data: {{ added_values_counts| safe }},
174+
borderColor: 'rgba(75, 192, 192, 1)',
175+
backgroundColor: 'rgba(75, 192, 192, 0.2)',
176+
tension: 0.1
177+
}]
178+
},
179+
options: {
180+
scales: {
181+
y: {
182+
beginAtZero: true
183+
}
184+
}
185+
}
186+
});
187+
188+
var eventCtx = document.getElementById('eventChart').getContext('2d');
189+
var eventChart = new Chart(eventCtx, {
190+
type: 'line',
191+
data: {
192+
labels: {{ event_dates| safe }},
193+
datasets: [{
194+
label: 'Event Count',
195+
data: {{ event_counts| safe }},
196+
borderColor: 'rgba(153, 102, 255, 1)',
197+
backgroundColor: 'rgba(153, 102, 255, 0.2)',
198+
tension: 0.1
199+
}]
200+
},
201+
options: {
202+
scales: {
203+
y: {
204+
beginAtZero: true
205+
}
206+
}
207+
}
208+
});
209+
210+
document.getElementById('timeRangeSelector').addEventListener('change', function () {
211+
window.location.href = '{% url "admin_dashboard" %}?time_range=' + this.value;
212+
});
213+
214+
document.getElementById('eventTypeSelector').addEventListener('change', function () {
215+
window.location.href = '{% url "admin_dashboard" %}?event_type=' + this.value + '&event_time_range=' + document.getElementById('eventTimeRangeSelector').value;
216+
});
217+
218+
document.getElementById('eventTimeRangeSelector').addEventListener('change', function () {
219+
window.location.href = '{% url "admin_dashboard" %}?event_type=' + document.getElementById('eventTypeSelector').value + '&event_time_range=' + this.value;
220+
});
221+
});
222+
</script>
223+
{% endblock %}

server/django/sensordata/templates/base.html

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,15 @@
3535
</p>
3636
</a>
3737
</li>
38-
3938
<li class="nav-item">
40-
<a href="{% url 'firmware_dashboard' %}"
41-
class="nav-link {% if request.path == '/firmware_dashboard/' %}active{% endif %}">
39+
<a href="{% url 'device_dashboard' %}"
40+
class="nav-link {% if request.path == '/device_dashboard/' %}active{% endif %}">
4241
<i class="nav-icon fas fa-microchip"></i>
4342
<p>
44-
Firmware Update
43+
Device Dashboard
4544
</p>
4645
</a>
4746
</li>
48-
4947
<li class="nav-item">
5048
<a href="{% url 'event_dashboard' %}"
5149
class="nav-link {% if request.path == '/event_dashboard/' %}active{% endif %}">
@@ -55,23 +53,12 @@
5553
</p>
5654
</a>
5755
</li>
58-
59-
<li class="nav-item">
60-
<a href="{% url 'graph_dashboard' %}"
61-
class="nav-link {% if request.path == '/graph_dashboard/' %}active{% endif %}">
62-
<i class="nav-icon fas fa-chart-pie"></i>
63-
<p>
64-
Graph Dashboard
65-
</p>
66-
</a>
67-
</li>
68-
6956
<li class="nav-item">
70-
<a href="{% url 'pending_communication_dashboard' %}"
71-
class="nav-link {% if request.path == '/pending_communication_dashboard/' %}active{% endif %}">
72-
<i class="nav-icon fas fa-envelope"></i>
57+
<a href="{% url 'firmware_dashboard' %}"
58+
class="nav-link {% if request.path == '/firmware_dashboard/' %}active{% endif %}">
59+
<i class="nav-icon fas fa-microchip"></i>
7360
<p>
74-
Communications
61+
Firmware Update
7562
</p>
7663
</a>
7764
</li>
@@ -158,6 +145,11 @@ <h1 class="m-0">{{ title }}</h1>
158145
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.2/dist/js/bootstrap.bundle.min.js"></script>
159146
<script src="https://cdn.jsdelivr.net/npm/admin-lte@3.2/dist/js/adminlte.min.js"></script>
160147
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
148+
<script src="https://cdn.datatables.net/1.11.5/js/jquery.dataTables.min.js"></script>
149+
<script src="https://cdn.datatables.net/1.11.5/js/dataTables.bootstrap4.min.js"></script>
150+
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
151+
<link rel="stylesheet" href="https://cdn.datatables.net/1.11.5/css/dataTables.bootstrap4.min.css">
152+
{% block extra_js %}{% endblock %}
161153
</body>
162154

163155
</html>

0 commit comments

Comments
 (0)