-
Notifications
You must be signed in to change notification settings - Fork 0
/
ratepayer.py
185 lines (156 loc) · 6.23 KB
/
ratepayer.py
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
import pymongo
import flask
import json
import optparse
from urllib.parse import quote_plus
from flask import Flask
from flask import request
from pymongo import MongoClient
from checking import valid_datetime
from datetime import datetime
format_string = "%Y-%m-%dT%H:%M"
app = Flask(__name__)
# initalize the ratepayer from a config file
init_file = "ratepayer_config.json"
username = ""
password = ""
uri = ""
database = ""
collection = ""
with open(init_file) as json_data:
info = json.load(json_data)
username = info['username']
password = info['password']
uri = info['uri'] % (quote_plus(username), quote_plus(password))
database = info['database']
collection = info['collection']
# setup the connection to the database
client = MongoClient(uri)
db = client[database]
applicance_collection = db[collection]
# allow appliance to update the data base
# data will come in the form
# appliance_id, start_time, end_time, energy_usage
# def post_data(self, app_type, name, start, end, value):
# allow ratepayer's appliances to submit data to the ratepayer with the REST API
@app.route('/submit')
def record_data():
# get the passed parameters
appliance_id = request.args.get('id')
start_date = valid_datetime(request.args.get('start'))
end_date = valid_datetime(request.args.get('end'))
energy = request.args.get('energy')
print(str(type(start_date)))
# check all parameters exist
if (appliance_id is None or
start_date is None or
end_date is None or energy is None):
return 'ARGUMENT ERROR: Missing arguments'
# check if all parameters are valid
if float(energy) < 0:
return 'ARGUMENT ERROR: Energy below 0'
try:
db.appliances.update({'app_id': appliance_id}, {'app_id': appliance_id, 'type': 'unknown'}, upsert=True)
this_appliance = db.get_collection(str(appliance_id))
result = this_appliance.insert_one({
'start': start_date,
'end': end_date,
'energy': energy
})
except:
print("Error")
return "success"
#Get energy sum for a specific appliance ID belonging to this ratepayer.
#Start and end date must be supplied in the query string.
@app.route('/appliance/<appliance_id>')
def get_total_for_time_window(appliance_id):
assert str(appliance_id) in db.collection_names(), 'The database does not have any data for the given appliance'
start = valid_datetime(request.args.get('start'))
end = valid_datetime(request.args.get('end'))
assert start<=end, "start date must be before end"
total = 0.0
appliance_type = ''
try:
metadata = db.get_collection('appliances').find_one({'app_id': appliance_id})
appliance_type = metadata['type']
except:
appliance_type = 'unknown'
#filter energy records by time at the database before returning them to the application
try:
this_appliance = db.get_collection(str(appliance_id))
returned_entries = this_appliance.find({'start':{'$gte': start}, 'end':{'$lte':end}})
for e in returned_entries:
print (str(e))
total = total + float(e['energy'])
except:
print("error")
return "error"
#Create return string if the user requested power instead of energy
if return_power == "true":
timediff = (end - start)
hours_in_window = (timediff.total_seconds()) / 3600.0
print(str(hours_in_window))
power = total / hours_in_window
energy_info = {'appliance_id': appliance_id, 'appliance_type': appliance_type, 'power_total':power}
#Create return string if the user did not specify that power should be returned instead of energy
else:
energy_info = {'appliance_id': appliance_id, 'appliance_type': appliance_type, 'energy_total':total}
return json.dumps(energy_info)
#Get energy sum for all appliances belonging to this ratepayer.
#Start and end date must be supplied in the query string.
#If 'power=true' is supplied in the query string, power is returned instead of energy.
@app.route('/appliances/all')
def get_ratepayer_total():
#Get query string parameters
start = valid_datetime(request.args.get('start'))
end = valid_datetime(request.args.get('end'))
return_power = request.args.get('power')
print(return_power)
print(return_power == 'true')
assert start <=end, "start date must be before end"
type_selected = False
try:
#Allows user to specify a list of device types separated by commas
print("1")
required_types = request.args.get('types').split(',')
type_selected = True
except:
print("2")
type_selected = False
total = 0.0
appliances_count = 0
try:
for m in db.get_collection('appliances').find():
if type_selected is False or(type_selected and m['type'] in required_types):
appliances_count = appliances_count + 1
this_appliance = db.get_collection(str(m['app_id'])).find({'start':{'$gte': start}, 'end':{'$lte':end}})
for e in this_appliance:
total = total + float(e['energy'])
except:
print("error")
return "error"
#Create return string if the user requested power instead of energy
if return_power == "true":
timediff = (end - start)
hours_in_window = (timediff.total_seconds()) / 3600.0
print(str(hours_in_window))
power = total / hours_in_window
final_info = {'appliances_count': appliances_count, 'total_power': power}
#Create return string if the user did not specify that power should be returned instead of energy
else:
final_info = {'appliances_count': appliances_count, 'total_energy': total}
return json.dumps(final_info)
#Get list of all appliances belonging to this ratepayer.
#Appliance ID and appliance type are returned for each appliance.
#No energy data is returned.
@app.route('/appliances/list')
def list_appliances():
appliances_list = []
try:
for m in db.get_collection('appliances').find():
appliances_list.append({'appliance_id': m['app_id'], 'type':m['type']})
except:
print('error')
return json.dumps(appliances_list)
if __name__ == "__main__":
app.run(host='0.0.0.0')