Repository navigation
Expand file tree
/
Copy pathhandler.py
More file actions
138 lines (115 loc) · 4.61 KB
/
Copy pathhandler.py
File metadata and controls
138 lines (115 loc) · 4.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
""" definition of app specific models
moved into separate directory for the sake of maintainibility
"""
from math import ceil
from django.db import models
from django.core.exceptions import EmptyResultSet
from commons.epoch2str import epoch2str
from candc.configuration import FUNCTIONS
from candc.my_models.latest_data import latestData
from .my_models.emeter_reading import emeterReading
from .my_models.sliding_5min import Sliding_5min
from .my_models.sliding_15min import Sliding_15min
from .my_models.sliding_1min import Sliding_1min
class errorMessage:
def __init__(self, code="", msg=""):
self.code = code
self.msg = msg
class aggregateRecord:
"""structure for passing (the values of) an aggregate record
"""
#
def __init__(self, ts=-1, net=-1, pwr=0, wh=-1, cnt=-1):
self.ts = ts
self.net = net
self.pwr = pwr
self.wh = wh
self.cnt = cnt
class sampleRecord(aggregateRecord):
"""extending the aggregateRecord structure for passing (the values of) an aggregate record
with a few more sample period related data
"""
def __init__(self, *args, dt="", model="", period=-1, sample=-1, **kwargs):
super().__init__(*args, **kwargs)
self.dt = dt
self.model = model
self.period = period
self.sample = sample
def addSampleData(self, cls="", period=-1, sample=-1):
"""expects baseline sampleRecord instance
*with* ts (epoch timestamp) already initialized
"""
self.dt = epoch2str(self.ts)
self.model = cls
self.period = period
self.sample = sample
# t = [{
# "ts":1745916206,
# "net": 6590.701,
# "pwr": 5,
# . . .
# }]
#
class handlerClass():
""" class: handlerClass
"""
mdl_name = "UNKNOWN"
mdl_class = None
mapping = {
"emeterReading": emeterReading,
"Sliding_1min": Sliding_1min,
"Sliding_5min": Sliding_5min,
"Sliding_15min": Sliding_15min,
}
def __init__(self, model=None):
self.mdl_name = model
print(repr(self.mdl_name))
if self.mdl_name in self.mapping:
self.mdl_class = self.mapping[model]
self.sample = -1
self.period = -1
self.count = -1
for fnc, params in FUNCTIONS.items():
if params["target"] == self.mdl_name:
self.sample = params["sample"]
if "period" in params:
self.period = params["period"]
self.count = ceil(params["period"] / params["sample"])
break
def get_latest(self, offs=0):
""" returns the latest (most recent) record
"""
if self.mdl_class is None:
rec = errorMessage("SEVERE", f"model [{self.mdl_name}] is not supported")
else:
sub = models.Subquery(latestData.objects.filter(name=self.mdl_name).values('ts')[:1])
qset = latestData.objects.filter(name=self.mdl_name).values('ts')
print(qset.query)
# TO CHECK
# EITHER (ts + offset*period) equal (ts__max)
# OR (ts + offset*period) between (ts__max + 0,5, ts__max - 0,5)
if offs > 0:
qset = self.mdl_class.objects.filter(ts=sub - offs*self.period)[:1]
else:
qset = self.mdl_class.objects.filter(ts=sub)[:1]
if qset.count() > 0:
res = qset[0]
rec = sampleRecord(ts=res.ts, net=res.net, pwr=res.pwr, wh=res.wh, cnt=res.cnt)
rec.addSampleData(cls=self.mdl_name, period=self.period, sample=self.sample)
else:
rec = errorMessage("ERROR", f"model [{self.mdl_name}] has no matching 'latest'")
return rec
def get_periods(self, periods=0):
pass
def aggregate_reading(self, period):
# subquery to retrieve the most recent entry (= max(ts))
# based on a suggestion from copilot to run the equivalent of
# (SELECT ts FROM emeter_reading ORDER BY ts DESC LIMIT 1)
sub = models.Subquery(latestData.objects.filter(name=self.mdl_name).values('ts')[:1])
qryset = self.mdl_class.objects.filter(ts__gt=models.Subquery(sub) - period)
ts = qryset.aggregate(models.Max("ts"))["ts__max"]
net = qryset.aggregate(models.Max("net"))["net__max"]
pwr = qryset.aggregate(models.Avg("pwr"))["pwr__avg"]
wh = qryset.aggregate(models.Sum("wh"))["wh__sum"]
cnt = qryset.aggregate(models.Count("ts"))["ts__count"]
return aggregateRecord(ts=ts, net=net, pwr=pwr, wh=wh, cnt=cnt)