3
3
from django .views .generic .edit import UpdateView
4
4
from django .contrib .auth .mixins import UserPassesTestMixin , LoginRequiredMixin
5
5
from django .urls import reverse_lazy , reverse
6
+ from django .utils import timezone
7
+ from django .core .serializers .json import DjangoJSONEncoder
8
+ from django .core .paginator import Paginator
9
+ import json
6
10
7
-
8
- from .models import Device , DeviceStatus
11
+ from .models import Device , DeviceStatus , DeviceLogs
9
12
from .forms import DeviceForm , DeviceNotesForm
10
13
11
14
class DeviceListView (UserPassesTestMixin , ListView ):
@@ -21,18 +24,67 @@ def get_queryset(self):
21
24
return Device .objects .all ().order_by ('id' )
22
25
23
26
24
- class DeviceDetailView (UserPassesTestMixin , DetailView ):
27
+ class DeviceDetailView (LoginRequiredMixin , UserPassesTestMixin , DetailView ):
25
28
model = Device
26
29
context_object_name = 'device'
27
30
template_name = 'devices/detail.html'
28
31
29
32
def test_func (self ):
33
+ # Only superusers can access this view
30
34
return self .request .user .is_authenticated and self .request .user .is_superuser
31
35
32
36
def get_context_data (self , ** kwargs ):
33
37
context = super ().get_context_data (** kwargs )
34
- # Fetch all DeviceStatus entries related to this Device, ordered by most recent
35
- context ['device_statuses' ] = DeviceStatus .objects .filter (device = self .object ).order_by ('-time_received' )
38
+ device = self .object
39
+
40
+ # Fetch all DeviceStatus entries related to this Device, ordered by time_received ascendingly
41
+ device_status_qs = DeviceStatus .objects .filter (device = device ).order_by ('time_received' )
42
+ context ['battery_status' ] = device_status_qs .exists ()
43
+
44
+ if context ['battery_status' ]:
45
+ # Prepare data for Chart.js
46
+ battery_times = [
47
+ status .time_received .strftime ('%Y-%m-%d %H:%M' )
48
+ for status in device_status_qs
49
+ if status .battery_soc is not None and status .battery_voltage is not None
50
+ ]
51
+ battery_charges = [
52
+ min (max (status .battery_soc , 0 ), 100 )
53
+ for status in device_status_qs
54
+ if status .battery_soc is not None and status .battery_voltage is not None
55
+ ]
56
+ battery_voltages = [
57
+ round (status .battery_voltage , 2 )
58
+ for status in device_status_qs
59
+ if status .battery_soc is not None and status .battery_voltage is not None
60
+ ]
61
+
62
+ # Serialize data to JSON format
63
+ context ['battery_times' ] = json .dumps (battery_times , cls = DjangoJSONEncoder )
64
+ context ['battery_charges' ] = json .dumps (battery_charges , cls = DjangoJSONEncoder )
65
+ context ['battery_voltages' ] = json .dumps (battery_voltages , cls = DjangoJSONEncoder )
66
+
67
+ # Fetch all DeviceLogs entries related to this Device, ordered by timestamp descendingly
68
+ device_logs_qs = DeviceLogs .objects .filter (device = device ).order_by ('-timestamp' )
69
+
70
+ # Implement pagination (10 logs per page)
71
+ paginator = Paginator (device_logs_qs , 10 )
72
+ page_number = self .request .GET .get ('page' )
73
+ page_obj = paginator .get_page (page_number )
74
+
75
+ context ['device_logs' ] = page_obj
76
+ context ['paginator' ] = paginator
77
+ context ['page_obj' ] = page_obj
78
+
79
+ # Define a level to badge class mapping
80
+ context ['level_badge_map' ] = {
81
+ 10 : 'bg-secondary' , # DEBUG
82
+ 20 : 'bg-info' , # INFO
83
+ 30 : 'bg-warning' , # WARNING
84
+ 40 : 'bg-danger' , # ERROR
85
+ 50 : 'bg-dark' , # CRITICAL
86
+ }
87
+
36
88
return context
37
89
38
90
0 commit comments