Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
wattsworth
/
lumen-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
0986afad
authored
Jun 09, 2017
by
John Doe
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
added nilm_id to json for db_streams
parent
4d2b1f7e
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
154 additions
and
35 deletions
app/adapters/db_adapter.rb
app/controllers/db_elements_controller.rb
app/controllers/db_streams_controller.rb
app/services/data/load_element_data.rb
app/services/data/load_stream_data.rb
app/views/db_folders/_db_folder.json.jbuilder
app/views/db_folders/show.json.jbuilder
app/views/db_streams/_db_stream.json.jbuilder
app/views/db_streams/data.csv.erb
app/views/db_streams/index.json.jbuilder
app/views/db_streams/show.json.jbuilder
config/routes.rb
spec/controllers/db_elements_controller_spec.rb
spec/controllers/db_streams_controller_spec.rb
spec/factories/load_stream_data.rb
spec/services/data/load_stream_data_spec.rb
app/adapters/db_adapter.rb
View file @
0986afad
...
...
@@ -3,7 +3,10 @@
# Wrapper around NilmDB HTTP service
class
DbAdapter
include
HTTParty
default_timeout
10
default_timeout
5
open_timeout
5
read_timeout
5
attr_reader
:url
def
initialize
(
url
)
...
...
app/controllers/db_elements_controller.rb
View file @
0986afad
...
...
@@ -3,16 +3,7 @@ class DbElementsController < ApplicationController
before_action
:authenticate_user!
#def index
# @elements = DbElement.find(JSON.parse(params[:elements]))
# # make sure the user is allowed to view these elements
# @elements.each do |elem|
# unless current_user.views_nilm?(elem.db_stream.db.nilm)
# head :unauthorized
# return
# end
# end
#end
def
data
req_elements
=
DbElement
.
find
(
JSON
.
parse
(
params
[
:elements
]))
...
...
@@ -26,12 +17,28 @@ class DbElementsController < ApplicationController
# make sure the time range makes sense
start_time
=
(
params
[
:start_time
].
to_i
unless
params
[
:start_time
].
nil?
)
end_time
=
(
params
[
:end_time
].
to_i
unless
params
[
:end_time
].
nil?
)
#requested resolution (leave blank for max possible)
resolution
=
(
params
[
:resolution
].
to_i
unless
params
[
:resolution
].
nil?
)
# padding: percentage of data to retrieve beyond start|end
padding
=
params
[
:padding
].
nil?
?
0
:
params
[
:padding
].
to_f
# retrieve the data for the requested elements
@service
=
LoadElementData
.
new
@service
.
run
(
req_elements
,
start_time
,
end_time
)
@start_time
=
@service
.
start_time
@end_time
=
@service
.
end_time
#if start and end are specified, calculate padding
if
!
start_time
.
nil?
&&
!
end_time
.
nil?
actual_start
=
(
start_time
-
(
end_time
-
start_time
)
*
padding
).
to_i
actual_end
=
(
end_time
+
(
end_time
-
start_time
)
*
padding
).
to_i
@service
.
run
(
req_elements
,
actual_start
,
actual_end
,
resolution
)
@start_time
=
start_time
@end_time
=
end_time
#otherwise let the service determine the start/end automatically
else
@service
.
run
(
req_elements
,
start_time
,
end_time
,
resolution
)
@start_time
=
@service
.
start_time
@end_time
=
@service
.
end_time
end
render
status:
@service
.
success?
?
:
ok
:
:unprocessable_entity
end
...
...
app/controllers/db_streams_controller.rb
View file @
0986afad
...
...
@@ -7,6 +7,22 @@ class DbStreamsController < ApplicationController
before_action
:authorize_viewer
,
only:
[
:data
]
before_action
:authorize_owner
,
only:
[
:update
]
def
index
if
params
[
:streams
].
nil?
head
:unprocessable_entity
return
end
@streams
=
DbStream
.
find
(
JSON
.
parse
(
params
[
:streams
]))
# make sure the user is allowed to view these streams
@streams
.
each
do
|
stream
|
unless
current_user
.
views_nilm?
(
stream
.
db
.
nilm
)
head
:unauthorized
return
end
end
end
def
update
adapter
=
DbAdapter
.
new
(
@db
.
url
)
@service
=
EditStream
.
new
(
adapter
)
...
...
app/services/data/load_element_data.rb
View file @
0986afad
...
...
@@ -17,6 +17,8 @@ class LoadElementData
# start_time and end_time are unix us
# if start_time is nil it is set to earliest timestamp
# if end_time is nil it is set to latest timestamp
# if resolution is nil, retrieve highest resolution possible
#
# sets data
# data:
...
...
@@ -24,7 +26,7 @@ class LoadElementData
# {id: element_id, values: [...]},...]
# see load_stream_data for details on the value structure
#
def
run
(
elements
,
start_time
,
end_time
)
def
run
(
elements
,
start_time
,
end_time
,
resolution
=
nil
)
#1 figure out what streams need to be pulled
req_streams
=
[]
elements
.
each
do
|
elem
|
...
...
@@ -76,7 +78,7 @@ class LoadElementData
adapter
=
DbAdapter
.
new
(
stream
.
db
.
url
)
data_service
=
LoadStreamData
.
new
(
adapter
)
stream_elements
=
elements
.
select
{
|
e
|
e
.
db_stream_id
==
stream
.
id
}.
to_a
data_service
.
run
(
stream
,
@start_time
,
@end_time
,
stream_elements
)
data_service
.
run
(
stream
,
@start_time
,
@end_time
,
stream_elements
,
resolution
)
if
data_service
.
success?
combined_data
.
concat
(
data_service
.
data
)
...
...
app/services/data/load_stream_data.rb
View file @
0986afad
...
...
@@ -17,6 +17,8 @@ class LoadStreamData
# associated database, sets data and data_type
# specify a subset of elements as an optional array
# if ommitted, all elements are extracted from the stream (expensive!)
# optionally specify a resolution, if omitted, returns maximum resolution
# allowed by the nilm
#
# sets data and data_type
# data_type: raw
...
...
@@ -33,7 +35,7 @@ class LoadStreamData
# data:
# [{id: element_id, type: decimated, values: [[start,0],[end,0],nil,...]}]
#
def
run
(
db_stream
,
start_time
,
end_time
,
elements
=
[])
def
run
(
db_stream
,
start_time
,
end_time
,
elements
=
[]
,
resolution
=
nil
)
# if elements are not explicitly passed, get all of them
if
(
elements
.
empty?
)
...
...
@@ -41,7 +43,11 @@ class LoadStreamData
end
elements
.
sort_by!
(
&
:column
)
resolution
=
db_stream
.
db
.
max_points_per_plot
resolution
=
if
resolution
.
nil?
db_stream
.
db
.
max_points_per_plot
else
[
db_stream
.
db
.
max_points_per_plot
,
resolution
].
min
end
valid_decim
=
findValidDecimationLevel
(
db_stream
,
start_time
)
# valid_decim is the highest resolution, find one we can plot
plottable_decim
=
findPlottableDecimationLevel
(
...
...
@@ -98,9 +104,8 @@ class LoadStreamData
# the decimation level will be 0
#
def
findPlottableDecimationLevel
(
db_stream
,
valid_decim
,
start_time
,
end_time
,
_
resolution
db_stream
,
valid_decim
,
start_time
,
end_time
,
resolution
)
path
=
db_stream
.
path
path
+=
"~decim-
#{
valid_decim
.
level
}
"
if
valid_decim
.
level
>
1
# figure out how much data this stream has over the interval
...
...
@@ -112,16 +117,15 @@ class LoadStreamData
# find out how much raw data exists over the specified interval
raw_count
=
count
*
valid_decim
.
level
# now we can find the right decimation level for plotting
max_count
=
db_stream
.
db
.
max_points_per_plot
# if the valid decim can be plotted, use it
return
valid_decim
if
raw_count
<=
max_count
return
valid_decim
if
raw_count
<=
resolution
# otherwise look for a higher decimation level
found_valid_decim
=
false
db_stream
.
db_decimations
.
where
(
'level >= ?'
,
valid_decim
.
level
)
.
order
(
:level
)
.
each
do
|
decim
|
if
raw_count
/
decim
.
level
<=
max_count
if
raw_count
/
decim
.
level
<=
resolution
# the lowest decimation level is the best
return
decim
end
...
...
app/views/db_folders/_db_folder.json.jbuilder
View file @
0986afad
...
...
@@ -6,6 +6,7 @@ end
json.streams(db_folder.db_streams.includes(:db_elements)) do |stream|
json.extract! stream, *DbStream.json_keys
json.nilm_id nilm.id
json.elements(stream.db_elements) do |element|
json.extract! element, *DbElement.json_keys
end
...
...
app/views/db_folders/show.json.jbuilder
View file @
0986afad
# frozen_string_literal: true
json.partial! 'db_folders/db_folder',
db_folder: @db_folder
db_folder: @db_folder
, nilm: @nilm
app/views/db_streams/_db_stream.json.jbuilder
View file @
0986afad
# frozen_string_literal: true
json.extract! db_stream, *DbStream.json_keys
json.nilm_id db_stream.db.nilm.id
json.elements(db_stream.db_elements) do |element|
json.extract! element, *DbElement.json_keys
...
...
app/views/db_streams/data.csv.erb
View file @
0986afad
###############################################
# Stream:
<%=
@db_stream
.
name
%>
# Installation:
<%=
@nilm
.
name
%>
<%
unless
@nilm
.
description
.
blank?
%>
(
<%=
@nilm
.
description
%>
)
<%
end
%>
# Path:
<%=
@db_stream
.
path
%>
# Source:
<%=
@nilm
.
name
%>
<%
unless
@nilm
.
description
.
blank?
%>
(
<%=
@nilm
.
description
%>
)
<%
end
%>
#
# URL:
<%=
@nilm
.
url
%>
#
# start:
<%=
Time
.
at
(
@legend
[
:start_time
]
/
1
e6
)
%>
# end:
<%=
Time
.
at
(
@legend
[
:end_time
]
/
1
e6
)
%>
...
...
app/views/db_streams/index.json.jbuilder
0 → 100644
View file @
0986afad
json.array! @streams do |stream|
json.extract! stream, *DbStream.json_keys
json.nilm_id stream.db.nilm.id
json.elements(stream.db_elements) do |element|
json.extract! element, *DbElement.json_keys
end
end
app/views/db_streams/show.json.jbuilder
deleted
100644 → 0
View file @
4d2b1f7e
# frozen_string_literal: true
json.partial! 'db_streams/db_stream',
db_folder: @db_stream
config/routes.rb
View file @
0986afad
...
...
@@ -12,7 +12,7 @@ Rails.application.routes.draw do
end
resources
:dbs
,
only:
[
:show
,
:update
]
resources
:db_folders
,
only:
[
:show
,
:update
]
resources
:db_streams
,
only:
[
:update
]
do
resources
:db_streams
,
only:
[
:
index
,
:
update
]
do
member
do
post
'data'
end
...
...
spec/controllers/db_elements_controller_spec.rb
View file @
0986afad
...
...
@@ -18,8 +18,6 @@ RSpec.describe DbElementsController, type: :request do
stream
.
db_elements
<<
@elem2
end
it
"returns elements with data"
do
@service_data
=
[{
id:
@elem1
.
id
,
data:
'mock1'
},
{
id:
@elem2
.
id
,
data:
'mock2'
}]
@mock_service
=
instance_double
(
LoadElementData
,
...
...
@@ -40,6 +38,31 @@ RSpec.describe DbElementsController, type: :request do
body
=
JSON
.
parse
(
response
.
body
)
expect
(
body
[
'data'
].
count
).
to
eq
(
2
)
end
it
'computes padding if specified'
do
@service_data
=
[{
id:
@elem1
.
id
,
data:
'mock1'
},
{
id:
@elem2
.
id
,
data:
'mock2'
}]
@mock_service
=
instance_double
(
LoadElementData
,
run:
StubService
.
new
,
success?:
true
,
notices:
[],
warnings:
[],
errors:
[],
data:
@service_data
)
allow
(
LoadElementData
).
to
receive
(
:new
).
and_return
(
@mock_service
)
expect
(
@mock_service
).
to
receive
(
:run
).
with
([
@elem1
,
@elem2
],
90
,
210
,
nil
)
@auth_headers
=
user1
.
create_new_auth_token
get
'/db_elements/data.json'
,
params:
{
elements:
[
@elem1
.
id
,
@elem2
.
id
].
to_json
,
start_time:
100
,
end_time:
200
,
padding:
0.1
},
headers:
@auth_headers
expect
(
response
).
to
have_http_status
(
:ok
)
# check to make sure JSON renders the elements
body
=
JSON
.
parse
(
response
.
body
)
expect
(
body
[
'data'
].
count
).
to
eq
(
2
)
# reported time bounds should *NOT* include padding
body
[
'data'
].
map
do
|
data
|
expect
(
data
[
'start_time'
]).
to
eq
100
expect
(
data
[
'end_time'
]).
to
eq
200
end
end
it
'returns error if time bounds are invalid'
do
@auth_headers
=
user1
.
create_new_auth_token
get
'/db_elements/data.json'
,
...
...
spec/controllers/db_streams_controller_spec.rb
View file @
0986afad
...
...
@@ -12,7 +12,52 @@ RSpec.describe DbStreamsController, type: :request do
db:
john_nilm
.
db
)
end
# index action does not exist
describe
'GET index'
do
let
(
:viewer
)
{
create
(
:user
)}
let
(
:nilm
)
{
create
(
:nilm
,
viewers:
[
viewer
])}
let
(
:db
)
{
create
(
:db
,
nilm:
nilm
)}
let
(
:stream2
)
{
create
(
:db_stream
,
db:
db
)}
let
(
:stream1
)
{
create
(
:db_stream
,
db:
db
)}
let
(
:other_nilm
)
{
create
(
:nilm
)}
let
(
:other_db
)
{
create
(
:db
,
nilm:
other_nilm
)}
let
(
:other_stream
)
{
create
(
:db_stream
,
db:
other_db
)}
context
'with viewer permissions'
do
it
'returns array of requested streams'
do
@auth_headers
=
viewer
.
create_new_auth_token
get
"/db_streams.json"
,
params:
{
streams:
[
stream1
.
id
,
stream2
.
id
].
to_json
},
headers:
@auth_headers
expect
(
response
).
to
have_http_status
(
:ok
)
# check to make sure JSON renders the streams
streams
=
JSON
.
parse
(
response
.
body
)
expect
(
streams
.
count
).
to
eq
(
2
)
end
it
'returns unauthorized with a mix of allowed and forbidden streams'
do
@auth_headers
=
viewer
.
create_new_auth_token
get
"/db_streams.json"
,
params:
{
streams:
[
stream1
.
id
,
stream2
.
id
,
other_stream
.
id
].
to_json
},
headers:
@auth_headers
expect
(
response
).
to
have_http_status
(
:unauthorized
)
end
end
context
'without permissions'
do
it
'returns unauthorized'
do
@auth_headers
=
viewer
.
create_new_auth_token
get
"/db_streams.json"
,
params:
{
streams:
[
other_stream
.
id
].
to_json
},
headers:
@auth_headers
expect
(
response
).
to
have_http_status
(
:unauthorized
)
end
end
context
'without sign-in'
do
it
'returns unauthorized'
do
get
"/db_streams.json"
,
params:
{
streams:
[
stream1
.
id
,
stream2
.
id
].
to_json
}
expect
(
response
).
to
have_http_status
(
:unauthorized
)
end
end
end
# show action does not exist
describe
'PUT update'
do
...
...
spec/factories/load_stream_data.rb
View file @
0986afad
...
...
@@ -8,7 +8,7 @@ class MockLoadStreamData
@data
=
nil
@run_count
=
0
end
def
run
(
db_stream
,
start_time
,
end_time
,
elements
=
[])
def
run
(
db_stream
,
start_time
,
end_time
,
elements
=
[]
,
resolution
=
nil
)
@data
=
@dataset
.
select
{
|
d
|
d
[
:stream
]
==
db_stream
}.
first
[
:data
]
@run_count
+=
1
if
(
@data
==
nil
)
...
...
spec/services/data/load_stream_data_spec.rb
View file @
0986afad
...
...
@@ -34,7 +34,7 @@ RSpec.describe 'LoadStreamData' do
expect
(
@service
.
success?
).
to
be
true
expect
(
@service
.
data_type
).
to
eq
(
'decimated'
)
end
it
'finds
appropriate level based on nilm resolution
'
do
it
'finds
max allowed resolution by default
'
do
# expect level 16 decimation to meet plotting requirements
@service
.
run
(
@db_stream
,
10
,
90
)
expect
(
@mockAdapter
.
level_retrieved
).
to
eq
(
16
)
...
...
@@ -47,6 +47,19 @@ RSpec.describe 'LoadStreamData' do
@service
.
run
(
@db_stream
,
10
,
90
)
expect
(
@mockAdapter
.
level_retrieved
).
to
eq
(
64
)
end
it
'finds lower resolution if requested'
do
# expect level 64 decimation to meet plotting requirements
@service
.
run
(
@db_stream
,
10
,
90
,
[],
50
)
expect
(
@mockAdapter
.
level_retrieved
).
to
eq
(
64
)
# with higher resolution setting, level should stay the same
db
.
max_points_per_plot
=
425
;
db
.
save
@service
.
run
(
@db_stream
,
10
,
90
,
[],
50
)
expect
(
@mockAdapter
.
level_retrieved
).
to
eq
(
64
)
# when resolution > allowed, returns allowed
db
.
max_points_per_plot
=
26
;
db
.
save
@service
.
run
(
@db_stream
,
10
,
90
,
[],
1000
)
expect
(
@mockAdapter
.
level_retrieved
).
to
eq
(
64
)
end
it
'populates @data structure with decimated data'
do
@service
.
run
(
@db_stream
,
10
,
90
)
expect
(
@service
.
data
.
length
).
to
eq
3
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment