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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
|
if not modules then modules = { } end modules ['util-you'] = {
version = 1.002,
comment = "library for fetching data from youless kwk meter polling device",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE",
license = "see context related readme files"
}
-- See mtx-youless.lua and s-youless.mkiv for examples of usage.
require("util-jsn")
-- the library variant:
utilities = utilities or { }
local youless = { }
utilities.youless = youless
local lpegmatch = lpeg.match
local formatters = string.formatters
local http = socket.http
-- maybe just a special parser but who cares about speed here
local function fetch(url,what,i)
local url = formatters["http://%s/V?%s=%i&f=j"](url,what,i)
local data = http.request(url)
local result = data and utilities.json.tolua(data)
return result
end
-- "123" " 1,234"
local tovalue = lpeg.Cs((lpeg.R("09") + lpeg.P(1)/"")^1) / tonumber
-- "2013-11-12T06:40:00"
local totime = (lpeg.C(4) / tonumber) * lpeg.P("-")
* (lpeg.C(2) / tonumber) * lpeg.P("-")
* (lpeg.C(2) / tonumber) * lpeg.P("T")
* (lpeg.C(2) / tonumber) * lpeg.P(":")
* (lpeg.C(2) / tonumber) * lpeg.P(":")
* (lpeg.C(2) / tonumber)
local function get(url,what,i,data,average,variant)
if not data then
data = { }
end
while true do
local d = fetch(url,what,i)
if d and next(d) then
local c_year, c_month, c_day, c_hour, c_minute, c_seconds = lpegmatch(totime,d.tm)
if c_year and c_seconds then
local delta = tonumber(d.dt)
local tnum = os.time { year = c_year, month = c_month, day = c_day, hour = c_hour, minute = c_minute }
local v = d.val
for i=1,#v do
local newvalue = lpegmatch(tovalue,v[i])
if newvalue then
local t = tnum + (i-1)*delta
local current = os.date("%Y-%m-%dT%H:%M:%S",t)
local c_year, c_month, c_day, c_hour, c_minute, c_seconds = lpegmatch(totime,current)
if c_year and c_seconds then
local years = data.years if not years then years = { } data.years = years end
local d_year = years[c_year] if not d_year then d_year = { } years[c_year] = d_year end
local months = d_year.months if not months then months = { } d_year.months = months end
local d_month = months[c_month] if not d_month then d_month = { } months[c_month] = d_month end
local days = d_month.days if not days then days = { } d_month.days = days end
local d_day = days[c_day] if not d_day then d_day = { } days[c_day] = d_day end
if average then
d_day.average = newvalue
else
local hours = d_day.hours if not hours then hours = { } d_day.hours = hours end
local d_hour = hours[c_hour] if not d_hour then d_hour = { } hours[c_hour] = d_hour end
d_hour[c_minute] = newvalue
end
end
end
end
end
else
return data
end
i = i + 1
end
return data
end
-- day of month (kwh)
-- url = http://192.168.1.14/V?m=2
-- m = the number of month (jan = 1, feb = 2, ..., dec = 12)
-- hour of day (watt)
-- url = http://192.168.1.14/V?d=1
-- d = the number of days ago (today = 0, yesterday = 1, etc.)
-- 10 minutes (watt)
-- url = http://192.168.1.14/V?w=1
-- w = 1 for the interval now till 8 hours ago.
-- w = 2 for the interval 8 till 16 hours ago.
-- w = 3 for the interval 16 till 24 hours ago.
-- 1 minute (watt)
-- url = http://192.168.1.14/V?h=1
-- h = 1 for the interval now till 30 minutes ago.
-- h = 2 for the interval 30 till 60 minutes ago
function youless.collect(specification)
if type(specification) ~= "table" then
return
end
local host = specification.host or ""
local data = specification.data or { }
local filename = specification.filename or ""
local variant = specification.variant or "kwh"
local detail = specification.detail or false
local nobackup = specification.nobackup or false
if host == "" then
return
end
if name then
data = table.load(name) or data
end
if variant == "kwh" then
get(host,"m",1,data,true)
elseif variant == "watt" then
get(host,"d",0,data,true)
get(host,"w",1,data)
if detail then
get(host,"h",1,data)
end
end
if filename == "" then
return
end
local path = file.dirname(filename)
local base = file.basename(filename)
data.variant = variant
if nobackup then
-- saved but with checking
local tempname = file.join(path,"youless.tmp")
table.save(tempname,data)
local check = table.load(tempname)
if type(check) == "table" then
local keepname = file.replacesuffix(filename,"old")
os.remove(keepname)
if not lfs.isfile(keepname) then
os.rename(filename,keepname)
os.rename(tempname,filename)
end
end
else
local keepname = file.join(path,formatters["%s-%s"](os.date("%Y-%m-%d-%H-%M-%S",os.time()),base))
os.rename(filename,keepname)
if not lfs.isfile(filename) then
table.save(filename,data)
end
end
return data
end
-- local data = youless.collect {
-- host = "192.168.2.50",
-- variant = "watt",
-- filename = "youless-watt.lua"
-- }
-- inspect(data)
-- local data = youless.collect {
-- host = "192.168.2.50",
-- variant = "kwh",
-- filename = "youless-kwh.lua"
-- }
-- inspect(data)
function youless.analyze(data)
if data and data.variant == "watt" and data.years then
for y, year in next, data.years do
local a_year, n_year, m_year = 0, 0, 0
if year.months then
for m, month in next, year.months do
local a_month, n_month = 0, 0
if month.days then
for d, day in next, month.days do
local a_day, n_day = 0, 0
if day.hours then
for h, hour in next, day.hours do
local a_hour, n_hour, m_hour = 0, 0, 0
for k, v in next, hour do
if type(k) == "number" then
a_hour = a_hour + v
n_hour = n_hour + 1
if v > m_hour then
m_hour = v
end
end
end
n_day = n_day + n_hour
a_day = a_day + a_hour
hour.maxwatt = m_hour
hour.watt = a_hour / n_hour
if m_hour > m_year then
m_year = m_hour
end
end
end
if n_day > 0 then
a_month = a_month + a_day
n_month = n_month + n_day
day.watt = a_day / n_day
else
day.watt = 0
end
end
end
if n_month > 0 then
a_year = a_year + a_month
n_year = n_year + n_month
month.watt = a_month / n_month
else
month.watt = 0
end
end
end
if n_year > 0 then
year.watt = a_year / n_year
year.maxwatt = m_year
else
year.watt = 0
year.maxwatt = 0
end
end
end
end
|