-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathutils.py
131 lines (116 loc) · 3.51 KB
/
utils.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
import json
import urllib.request
import urllib.error
import time
from math import radians, cos, sin, asin, sqrt, log10, ceil, degrees, atan2
def api_call(base='https://api.helium.io/v1/', path=''):
if base[-1] != '/':
base += '/'
url = f"{base}{path}"
for i in range(0, 3):
try:
return json.load(urllib.request.urlopen(url))
except urllib.error.HTTPError as e:
time.sleep(.25 + 1 * i)
def load_hotspots(force=False):
try:
if force:
raise FileNotFoundError
with open('hotspots.json', 'r') as fd:
return json.load(fd)
except FileNotFoundError as e:
with open('hotspots.json','w') as fd:
cursor = None
hotspots = []
while True:
url = 'https://api.helium.io/v1/hotspots'
if cursor:
url += '?cursor=' + cursor
resp = json.load(urllib.request.urlopen(url))
cursor = resp.get('cursor')
if not resp.get('data'):
break
#print(resp.get('data'))
hotspots.extend(resp.get('data'))
print(f"found {len(hotspots)} hotspots, cursor={cursor}")
if len(resp.get('data', [])) < 1000:
break
json.dump(hotspots, fd, indent=2)
return hotspots
def haversine_km(lat1, lon1, lat2, lon2, return_heading=False):
"""
Calculate the great circle distance between two points
on the earth (specified in decimal degrees)
"""
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
# haversine formula
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * asin(sqrt(a))
r = 6371 # Radius of earth in kilometers. Use 3956 for miles
X = cos(lat2) * sin(dlon)
Y = cos(lat1)*sin(lat2) - sin(lat1)*cos(lat2)*cos(dlon)
b_rad = atan2(X, Y)
b = (degrees(b_rad) + 360) % 360
if return_heading:
return c * r, b
return c * r
def max_rssi(dist_km):
if dist_km < 0.001:
return -1000
return 28 + 1.8*2 - (20*log10(dist_km) + 20*log10(915) + 32.44)
def snr_min_rssi(snr):
"""
retuns the minimum rssi valid at given snr
:param snr:
:return:
"""
# ce
snr = int(ceil(snr))
snr_table = {
12: (-90, -35),
4: (-115, -112),
-4: (-125, -125),
16: (-90, -35),
-15: (-124, -124),
-6: (-124, -124),
-1: (-125, -125),
-2: (-125, -125),
5: (-115, -100),
14: (-90, -35),
-11: (-125, -125),
9: (-95, -45),
10: (-90, -40),
-12: (-125, -125),
-7: (-123, -123),
-10: (-125, -125),
-14: (-125, -125),
2: (-117, -112),
6: (-113, -100),
-5: (-125, -125),
3: (-115, -112),
-3: (-125, -125),
1: (-120, -117),
7: (-108, -45),
8: (-105, -45),
-8: (-125, -125),
0: (-125, -125),
13: (-90, -35),
-16: (-123, -123),
-17: (-123, -123),
-18: (-123, -123),
-19: (-123, -123),
-20: (-123, -123),
15: (-90, -35),
-9: (-125, -125),
-13: (-125, -125),
11: (-90, -35)
}
if snr not in snr_table:
return 1000
return snr_table[snr][0]
if __name__ == '__main__':
#print(haversine_km(36, -120, 36, -119, return_heading=True))
load_hotspots(True)