-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathclimate_create_seekpoint.py
More file actions
287 lines (241 loc) · 13.3 KB
/
climate_create_seekpoint.py
File metadata and controls
287 lines (241 loc) · 13.3 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
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
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
import sys
import time
import json
import urllib3
import requests
import argparse
import calendar
from datetime import datetime, timedelta
# to disable warnings for not verifying host
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class Climate:
def __init__(self, cli_args):
# initializes argument parser
arg_parser = self.__initialize_argument_parser()
self.args = arg_parser.parse_args(cli_args)
self.api_url = "https://api2.rhombussystems.com"
# starts one API session that is used by all requests
self.api_sess = requests.session()
self.api_sess.headers = {
"Accept": "application/json",
"x-auth-scheme": "api-token",
"Content-Type": "application/json",
"x-auth-apikey": self.args.APIkey
}
today = datetime.now().replace(microsecond=0, second=0, minute=0)
self.end_time = today
self.start_time = (self.end_time - timedelta(days=365))
@staticmethod
def __initialize_argument_parser():
parser = argparse.ArgumentParser(
description = "Gets the rate of change of the temperature."
)
# command line arguments for user
parser.add_argument("APIkey", type=str, help="Get this from your console")
parser.add_argument("sensorName", type=str, help="Name of the Environmental Sensor")
parser.add_argument("option", type = str, help = "Whether the program should look for past or present events", choices = ["Past", "Present"])
parser.add_argument("--time", type=str, help="yyyy-mm-dd (0):00:00")
parser.add_argument("--tempRate", type = float, help = "The limit for which the ratechange of the temperature is OK.", default = 0.15)
parser.add_argument("--humidRate", type = float, help = "The limit for which the ratechange of the humidity is OK.", default = 0.15)
parser.add_argument("--cameraName", type = str, help = 'Name of the camera that is associated with the environmental sensor.')
return parser
# converts human time to milliseconds
def milliseconds_time(self, human):
# the +25200000 is to get local time and not GMT
ms_time = (calendar.timegm(time.strptime(human, '%Y-%m-%d %H:%M:%S')) * 1000) + 25200000
return ms_time
# converts ms time to timestamp
def human_time(self, event):
event = event/1000
timestamp = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime(event))
return timestamp
# converts milliseconds to minutes
def ms_convert(self, milliseconds):
seconds = milliseconds / 1000
minutes = seconds / 60
return minutes
# converts sensor name to sensor uuid
def sensor_name_convert(self):
for value in self.sensor_data['climateStates']:
if self.args.sensorName == value['name']:
return value['sensorUuid']
# converts camera name to camera uuid
def camera_name_convert(self):
for value in self.camera_data['cameraStates']:
if self.args.cameraName == value['name']:
return value['uuid']
# converts Celsius to Fahrenheit
def celsius_convert(self, celsius):
fahrenheit = (celsius * 1.8) + 32
return fahrenheit
# returns data that is used to convert sensor namse to uuid
def sensor(self):
endpoint = self.api_url + "/api/climate/getMinimalClimateStateList"
payload = {
}
resp = self.api_sess.post(endpoint, json = payload,
verify = False)
content = resp.content
sensor_data = json.loads(content)
return sensor_data
# returns data that is used to convert camera name to uuid
def camera_data(self):
endpoint = self.api_url + "/api/camera/getMinimalCameraStateList"
payload = {
}
resp = self.api_sess.post(endpoint, json = payload,
verify = False)
content = resp.content
data = json.loads(content)
return data
# returns temperature and humidity data
def climate_data(self, start_time, end_time):
endpoint = self.api_url + "/api/climate/getClimateEventsForSensor"
self.sensor_data = self.sensor()
self.sensor_uuid = self.sensor_name_convert()
payload = {
"sensorUuid": self.sensor_uuid,
"createdAfterMs": start_time,
"createdBeforeMs": end_time
}
resp = self.api_sess.post(endpoint, json=payload,
verify=False)
content = resp.content
data = json.loads(content)
return data
# creates seekpoint
def create_seekpoint(self):
self.camera_data = self.camera_data()
if self.args.cameraName:
self.cameraUuid = self.camera_name_convert()
else:
for value in self.sensor_data['climateStates']:
if len(value["associatedCameras"]) > 0:
self.cameraUuid = value['associatedCameras'][0]
# 'associatedCameras' is a list
# program will use the first value in the list
else:
# if there are no camera uuids in the list
print("There are no cameras associated with this sensor.")
return
endpoint = self.api_url + "/api/camera/createFootageSeekpoints"
payload = {
"footageSeekPoint": {
"a": "CUSTOM",
"cdn": "Rapid Temp/Humidity Change",
"ts": self.ms_time
},
"cameraUuid": self.cameraUuid
}
resp = self.api_sess.post(endpoint, json=payload,
verify=False)
content = resp.content
data = json.loads(content)
return data
def execute(self):
temp_rate_min = None # declaring temp_rate_min to validate the date
humid_rate_min = None # declaring humid_rate_min to validate the date
count = 0
if self.args.option == "Past":
if self.args.time:
self.ms_time = self.milliseconds_time(self.args.time) # if input, converting timestamp to milliseconds
else:
self.ms_time = int(round((time.time() - 60 * 60 * 2) * 1000)) # defaults to two hours ago
ms_time_begin = self.ms_time - (15 * 60 * 1000) # start time of data collection is 15 minutes before ms_time
ms_time_end = self.ms_time + (15 * 60 * 1000) # end time of data collection is 15 minutes after ms_time
climate_data = self.climate_data(ms_time_begin, ms_time_end)
if 'climateEvents' not in climate_data: # input validation for sensor name
print("There is no data for that tag name.")
return
# running through times in ms (greatest to least)
for earlier_time in climate_data['climateEvents']:
count += 1
# in milliseconds, an earlier time would be a lesser number than a later time
if earlier_time['timestampMs'] < self.ms_time:
later_time = climate_data['climateEvents'][count - 2]
# later_time is the closest time that is later than ms_time
time_dif_ms = later_time['timestampMs'] - earlier_time['timestampMs'] # time difference in milliseconds
time_dif_min = self.ms_convert(time_dif_ms) # ms time difference is converted to minutes
temp_dif = self.celsius_convert(later_time['temp']) - self.celsius_convert(earlier_time['temp'])
# calculate temperature difference between the two times in Fahrenheit
humid_dif = later_time['humidity'] - earlier_time['humidity']
# calculate humidity difference between the two times
temp_rate_min = temp_dif / time_dif_min # change in temperature per minute
humid_rate_min = humid_dif / time_dif_min # change in humidity per minute
if temp_rate_min == None or humid_rate_min == None: # no data generated if temp_rate_min is still None, date must be invalid
print("There are no data for the data.")
return
print("Temperature rate of change: ", temp_rate_min)
print("Humidity rate of change: ", humid_rate_min)
# if rate at which the temperature is changing exceeds threshold
if temp_rate_min > self.args.tempRate or temp_rate_min < -self.args.tempRate:
self.create_seekpoint()
if self.cameraUuid == None: # self.cameraUuid will be none if cameraName is invalid
print("Invalid camera name, no seekpoint created.")
else:
print("Temperature exceeded threshold, seekpoint created.")
# if rate at which the humidity is changing exceeds threshold
elif humid_rate_min > self.args.humidRate or humid_rate_min < -self.args.humidRate:
self.create_seekpoint()
if self.cameraUuid == None: # self.cameraUuid will be none if cameraName is invalid
print("Invalid camera name, no seekpoint created.")
else:
print("Humidity exceeded threshold, seekpoint created.")
else:
print("No seekpoints created.")
else: # if the user chose the option of past
running = True
temp_list = [] # list of temperature in Fahrenheit
humid_list = [] # list of humidities
time_list = [] # list of times in milliseconds
while running == True:
try:
print("Processing ... ")
end_time = int(round(time.time() * 1000)) # end time of data collection is always the current time
start_time = end_time - (1000 * 210) # start time of data collection is always 210 seconds before current time
climate_data = self.climate_data(start_time, end_time)
for value in climate_data['climateEvents']:
if self.celsius_convert(value['temp']) not in temp_list:
temp_list.append(self.celsius_convert(value['temp'])) # append fahrenheit to temp_list
humid_list.append(value['humidity']) # append humidity to humid_list
time_list.append(value['timestampMs']) # append milliseconds to time_list
count = 0
if len(temp_list) > 1: # if there are multiple events
# running through the events
while count < len(temp_list) - 1:
# calc the time difference between events in milliseconds
time_dif_ms = time_list[count + 1] - time_list[count]
time_dif_min = time_dif_ms / 1000 / 60 # convert time difference to seconds
# calc difference in temperature (Fahrenheit)
temp_dif = self.celsius_convert(temp_list[count + 1]) - self.celsius_convert(temp_list[count])
humid_dif = humid_list[count] - humid_list[count + 1] # calc difference in humidity
temp_rate_min = temp_dif / time_dif_min # rate at which the temperature is changing
print("Temp rate: ", temp_rate_min)
humid_rate_min = humid_dif / time_dif_min # rate at which the humidity is changing
print("Humid rate: ", humid_rate_min)
# if rate at which the temperature is changing exceeds threshold
if temp_rate_min > self.args.tempRate or temp_rate_min < -self.args.tempRate:
self.ms_time = end_time
self.create_seekpoint()
print("Temperature rate of change exceeds threshold, seekpoint created.")
return
else:
print("Temperature rate of change: ", temp_rate_min)
print("Temperate rate of chane does not exceed threshold, no seekpoint created.")
# if rate at which the humidity is changing exceeds threshold
if humid_rate_min > self.args.humidRate or humid_rate_min < -self.args.humidRate:
self.ms_time = end_time
self.create_seekpoint()
print("Humidity rate of change exceeds threshold, seekpoint created.")
return
else:
print("Humidity rate of change: ", humid_rate_min) # TODO: create placeholder
print("Humidity rate of change does not exceed threshold, no seekpoint created.")
count += 1
time.sleep(60) # sleep for one minute before each data collection
except:
print("Remote end closed connection without response.")
return
if __name__ == "__main__":
engine = Climate(sys.argv[1:])
engine.execute()