-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathsensor_log_receiving_service.py
executable file
·143 lines (114 loc) · 5.02 KB
/
sensor_log_receiving_service.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
#!/usr/bin/python3
# SPDX-License-Identifier: BSD-3-Clause
#
# Copyright 2019 Raritan Inc. All rights reserved.
from http.server import HTTPServer, BaseHTTPRequestHandler
import argparse, json, os
from netifaces import interfaces, ifaddresses, AF_INET
import os.path
def parse_cmdline():
DESCR = """Starts a server which handles Xerus data push sensor log messages."""
USAGE = "Usage: %prog [options]"
script_name = os.path.splitext(os.path.basename(__file__))[0]
default_path = "/tmp"
default_output_file_path = "{0}/{1}.csv".format(default_path, script_name)
parser = argparse.ArgumentParser(usage = USAGE, description = DESCR)
h = "General options"
grp = parser.add_argument_group(parser, h)
grp.add_argument("-o", "--output", dest = "sensor_output_file_arg", default = default_output_file_path, help = "write received sensor logs to this file")
grp.add_argument("-p", "--port", type=int, dest = "port_arg", default = 5080, help = "Port to connect to")
return parser.parse_args()
class SensorPushHandler(BaseHTTPRequestHandler):
SEPERATOR = ";"
TIMESTAMP_ATTR = 'timestamp'
LABEL_ATTR = 'label'
ID_ATTR = 'id'
STATE_ATTR = 'state'
AVG_VALUE_ATTR = 'avgValue'
def generate_csv_line(self, data_list):
str_list = [ str(string) for string in data_list ]
return self.SEPERATOR.join(str_list)
def write_csv(self, fname, json_data):
sensors = json_data['sensors']
rows = json_data['rows']
if len(sensors) > 0 and len(rows) > 0:
titles = [ self.TIMESTAMP_ATTR ]
for index, sensor in enumerate(sensors):
label = sensor['device'][self.LABEL_ATTR].replace(" ", "-")
sensor_id = sensor[self.ID_ATTR]
sensor_title = "{0}_{1}_{2}".format(index, sensor_id, label)
state_val_title = "{0}.{1}".format(sensor_title, self.STATE_ATTR)
avg_val_title = "{0}.{1}".format(sensor_title, self.AVG_VALUE_ATTR)
sensor_titles = [ state_val_title, avg_val_title ]
titles.extend(sensor_titles)
file_aready_exists = os.path.isfile(fname)
with open(fname, mode="a+", encoding = "utf-8") as fd:
titles_str = self.generate_csv_line(titles)
if not file_aready_exists:
fd.write(titles_str)
else:
# Move to the beginning of the file
fd.seek(0)
lines = fd.readlines()
last_line = lines[-1].split(self.SEPERATOR)
# Move to the end of the file
fd.seek(0, os.SEEK_END)
if len(titles) != len(last_line):
fd.write("\n\n" + titles_str)
for index, row in enumerate(rows):
timestamp = row[self.TIMESTAMP_ATTR]
sensor_data = [ timestamp ]
for record in row['records']:
state_value = record[self.STATE_ATTR]
avg_value = record[self.AVG_VALUE_ATTR]
record_data = [ state_value, avg_value ]
sensor_data.extend(record_data)
sensor_data_str = self.generate_csv_line(sensor_data)
fd.write("\n" + sensor_data_str)
else:
print("Sensor data was empty.")
def do_POST(self):
content_length = int(self.headers['Content-Length'])
body = self.rfile.read(content_length)
self.send_response(200)
self.end_headers()
data_str = body.decode("utf-8")
data = json.loads(data_str)
self.write_csv(sensor_output_file, data)
class SensorLogListenerServer():
httpd = None
def __init__(self, port):
# listen to everything not only localhost
self.address = ("", port)
self.start()
def __del__(self):
self.stop()
def stop(self):
if self.httpd != None:
print("Shutting down server.")
self.httpd.shutdown()
self.httpd.server_close()
def start(self):
try:
self.httpd = HTTPServer(self.address, SensorPushHandler)
self.httpd.serve_forever()
except KeyboardInterrupt:
exit(1)
def ip4_addresses():
ip_list = []
for interface in interfaces():
addrs = ifaddresses(interface)
if AF_INET in addrs:
for link in addrs[AF_INET]:
if 'addr' in link:
ip_addr = link['addr']
ip_addr_str = "http://{0}:{1}".format(ip_addr, args.port_arg)
ip_list.append(ip_addr_str)
return ip_list
args = parse_cmdline()
sensor_output_file = os.path.expanduser(args.sensor_output_file_arg)
ip_addresses_str = ", ".join(ip4_addresses())
print("Starting server and listen on the following addresses: {0}".format(ip_addresses_str))
print("Writing received data to '{0}'".format(sensor_output_file))
server = SensorLogListenerServer(args.port_arg)
server.start()