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
|
#!/usr/bin/env python3
#
# Copyright 2020 Daniel Friesel
#
# SPDX-License-Identifier: BSD-2-Clause
import numpy as np
import paho.mqtt.client as mqtt
import re
import requests
import serial
import serial.threaded
import time
class SerialReader(serial.threaded.Protocol):
"""
Character- to line-wise data buffer for serial interfaces.
Reads in new data whenever it becomes available and exposes a line-based
interface to applications.
"""
def __init__(self, callback):
"""Create a new SerialReader object."""
self.callback = callback
self.recv_buf = ''
def __call__(self):
return self
def data_received(self, data):
"""Append newly received serial data to the line buffer."""
try:
str_data = data.decode('UTF-8')
self.recv_buf += str_data
# We may get anything between \r\n, \n\r and simple \n newlines.
# We assume that \n is always present and use str.strip to remove leading/trailing \r symbols
# Note: Do not call str.strip on lines[-1]! Otherwise, lines may be mangled
lines = self.recv_buf.split('\n')
if len(lines) > 1:
self.recv_buf = lines[-1]
for line in lines[:-1]:
self.callback(str.strip(line))
except UnicodeDecodeError:
pass
#sys.stderr.write('UART output contains garbage: {data}\n'.format(data = data))
class SerialMonitor:
"""SerialMonitor captures serial output for a specific amount of time."""
def __init__(self, port: str, baud: int, callback):
"""
Create a new SerialMonitor connected to port at the specified baud rate.
Communication uses no parity, no flow control, and one stop bit.
Data collection starts immediately.
"""
self.ser = serial.serial_for_url(port, do_not_open=True)
self.ser.baudrate = baud
self.ser.parity = 'N'
self.ser.rtscts = False
self.ser.xonxoff = False
try:
self.ser.open()
except serial.SerialException as e:
sys.stderr.write('Could not open serial port {}: {}\n'.format(self.ser.name, e))
sys.exit(1)
self.reader = SerialReader(callback = callback)
self.worker = serial.threaded.ReaderThread(self.ser, self.reader)
self.worker.start()
def close(self):
"""Close serial connection."""
self.worker.stop()
self.ser.close()
if __name__ == '__main__':
mqtt = mqtt.Client()
mqtt.connect('172.23.225.193');
accel_factor = 2. / 32768
gyro_factor = 250. / 32768
magnet_factor = 150e-9
accel_minmax = np.zeros((6))
gyro_minmax = np.zeros((6))
magnet_minmax = np.zeros((6))
max_accel = 0
max_magnet = 0
vcc = 0
intervals = [60, 300, 600, 3600, 7200]
accel_by_5s = list()
step = 0
def parse_line(line):
global max_accel
global max_magnet
global vcc
match = re.match('button(.)', line)
if match:
mqtt.publish('sensor/button', int(match.group(1)))
match = re.match('Min Accel: ([^ ]+) / ([^ ]+) / ([^ ]+)', line)
if match:
accel_minmax[0] = int(match.group(1)) * accel_factor
accel_minmax[1] = int(match.group(2)) * accel_factor
accel_minmax[2] = int(match.group(3)) * accel_factor
match = re.match('Max Accel: ([^ ]+) / ([^ ]+) / ([^ ]+)', line)
if match:
accel_minmax[3] = int(match.group(1)) * accel_factor
accel_minmax[4] = int(match.group(2)) * accel_factor
accel_minmax[5] = int(match.group(3)) * accel_factor
match = re.match('Min Gyro: ([^ ]+) / ([^ ]+) / ([^ ]+)', line)
if match:
gyro_minmax[0] = int(match.group(1)) * gyro_factor
gyro_minmax[1] = int(match.group(2)) * gyro_factor
gyro_minmax[2] = int(match.group(3)) * gyro_factor
match = re.match('Max Gyro: ([^ ]+) / ([^ ]+) / ([^ ]+)', line)
if match:
gyro_minmax[3] = int(match.group(1)) * gyro_factor
gyro_minmax[4] = int(match.group(2)) * gyro_factor
gyro_minmax[5] = int(match.group(3)) * gyro_factor
match = re.match('Min Magnet: ([^ ]+) / ([^ ]+) / ([^ ]+)', line)
if match:
magnet_minmax[0] = int(match.group(1)) * magnet_factor
magnet_minmax[1] = int(match.group(2)) * magnet_factor
magnet_minmax[2] = int(match.group(3)) * magnet_factor
match = re.match('Max Magnet: ([^ ]+) / ([^ ]+) / ([^ ]+)', line)
if match:
magnet_minmax[3] = int(match.group(1)) * magnet_factor
magnet_minmax[4] = int(match.group(2)) * magnet_factor
magnet_minmax[5] = int(match.group(3)) * magnet_factor
match = re.match('CPU VCC: ([^ ]+)', line)
if match:
vcc = int(match.group(1))
match = re.match('MPU Temp: ([^ ]+)', line)
if match:
temp = float(match.group(1))
max_accel = np.linalg.norm(accel_minmax[:3] - accel_minmax[3:])
max_magnet = np.linalg.norm(magnet_minmax[3:])
mqtt.publish('sensor/accel_g', max_accel)
mqtt.publish('sensor/flux_t', max_magnet)
#mqtt.publish('sensor/gyro_dps', np.linalg.norm(gyro_minmax[:3] - gyro_minmax[3:]))
requests.post('http://192.168.0.200:8086/write?db=hosts', data='embedded,name=structure,area=hm17 mpu9250_degc={:f},mpu9250_mv={:d}'.format(temp, vcc))
monitor = SerialMonitor('/dev/ttyUSB0', 57600, parse_line)
try:
while True:
time.sleep(5)
accel_by_5s.append(max_accel)
step += 1
if step == 4:
for interval in intervals:
index_interval = int(interval / 5)
mqtt.publish('sensor/accel{}'.format(interval), max(accel_by_5s[ -index_interval : ]))
accel_by_5s = accel_by_5s[ -intervals[-1] : ]
step = 0
except KeyboardInterrupt:
monitor.close()
mqtt.disconnect()
|