-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy patharf8084.py
81 lines (61 loc) · 2.26 KB
/
arf8084.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
"""
Decode gps data format from Adeunis-RF ARF8084 BA
https://github.com/decentlab/coverage-mapper/blob/master/covmap/arf8084.py
"""
import logging
import struct
import base64
TEMP_BIT = 7
ACC_BIT = 6
BTN_BIT = 5
GPS_BIT = 4
UPCNTR_BIT = 3
DOWNCNTR_BIT = 2
BATTERY_BIT = 1
RSSISNR_BIT = 0
logger = logging.getLogger(__name__)
DECODE_MAP = [(TEMP_BIT, 'b', lambda x: x, 'temperature'),
# (ACC_BIT, '', lambda x: x, 'accelerometer_triggered'),
# (BTN_BIT, '', lambda x: x, 'button_pressed'),
(GPS_BIT, '8s', lambda x: (gpslat_frombcd(x[:4]),
gpslon_frombcd(x[4:])), 'lat_lon'),
(UPCNTR_BIT, 'B', lambda x: x, 'up_counter'),
(DOWNCNTR_BIT, 'B', lambda x: x, 'down_counter'),
(BATTERY_BIT, 'H', lambda x: x / 1000.0, 'battery_voltage'),
(RSSISNR_BIT, '2s', lambda x: (x), 'rssi_sinr')]
def gps_todec(hem, deg, min=0, sec=0):
return (deg + min / 60.0 + sec / 3600.0) * (-2 * hem + 1)
def gpslat_frombcd(bcd):
assert len(bcd) == 4
num = [x for x in bcd]
deg = (num[0] >> 4) * 10.0 + (num[0] & 0xf)
min = ((num[1] >> 4) * 10.0 + (num[1] & 0xf) +
(num[2] >> 4) / 10.0 + (num[2] & 0xf) / 100.0 +
(num[3] >> 4) / 1000.0)
hem = num[3] & 1
return gps_todec(hem, deg, min)
def gpslon_frombcd(bcd):
assert len(bcd) == 4
num = [x for x in bcd]
deg = (num[0] >> 4) * 100.0 + (num[0] & 0xf) * 10.0 + (num[1] >> 4)
min = ((num[1] & 0xf) * 10.0 + (num[2] >> 4) +
(num[2] & 0xf) / 10.0 + (num[3] >> 4) / 100.0)
hem = num[3] & 1
return gps_todec(hem, deg, min)
def decode(data):
logger.debug("decoding data: %r", data)
present = [spec
for spec
in DECODE_MAP
if (data[0] & (1 << spec[0])) != 0]
fmt = '>' + ''.join(x[1] for x in present)
items = struct.unpack(fmt, data[1:])
decoded = ((name, fun(bytes))
for (_, _, fun, name), bytes
in zip(present, items))
return dict(decoded)
def parse_coords(data_point):
data = decode(base64.b64decode(data_point['data']))
if 'lat_lon' not in data:
raise ValueError('Invalid GPS data')
return (data['lat_lon'][1], data['lat_lon'][0])