-
Notifications
You must be signed in to change notification settings - Fork 5
/
create_community_files.py
103 lines (84 loc) · 3.41 KB
/
create_community_files.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
#!/usr/bin/env python3
# Copyright 2016, Steffen Pankratz.
# SPDX-License-Identifier: AGPL-3
# For license see LICENSE or http://spdx.org/licenses/AGPL-3.0
from math import sin, cos, sqrt, asin, radians
import datetime
import json
import os
import urllib.request
import sys
def get_json_data_from_url(url):
return json.loads(urllib.request.urlopen(url).read().decode())
def get_json_data_from_file(file):
with open(file, 'r', encoding='utf-8') as json_file:
return json.load(json_file)
def get_distance_in_km(point_x, point_y):
lat_x = point_x['lat']
lon_x = point_x['lon']
lat_y = point_y['lat']
lon_y = point_y['lon']
dlon = lon_y - lon_x
dlat = lat_y - lat_x
a = sin(dlat / 2) ** 2 + cos(lat_x) * cos(lat_y) * sin(dlon / 2) ** 2
c = 2 * asin(sqrt(a))
radius = 6373.0 # approximate radius of earth in km
return radius * c
def merge(a, b, path=None):
if path is None:
path = []
for key in b:
if key in a:
if isinstance(a[key], dict) and isinstance(b[key], dict):
merge(a[key], b[key], path + [str(key)])
elif isinstance(a[key], list) and isinstance(b[key], list):
a[key].extend(b[key])
elif a[key] == b[key]:
pass # same value
else:
pass # keep value from a
else:
a[key] = b[key]
return a
def get_router_count_by_community(routers, community):
router_count_by_community = 0
point_y = {
'lat': radians(float(community['data']['location']['geoCode']['lat'])),
'lon': radians(float(community['data']['location']['geoCode']['lon']))
}
for router in routers:
if get_distance_in_km(router, point_y) < community['radius']:
router_count_by_community += 1
return router_count_by_community
def get_online_routers(nodelist_data):
routers = []
for router in nodelist_data['nodes']:
if router['status']['online'] and 'position' in router:
routers.append(
{'lat': radians(router['position']['lat']),
'lon': radians(router['position']['long'])})
return routers
def update_community_files(nodelist_url, communities_file, output_dir):
nodelist_data = get_json_data_from_url(nodelist_url)
routers = get_online_routers(nodelist_data)
community_data = get_json_data_from_file(communities_file)
for community in community_data['communities']:
merge(community, community_data['metacommunity'])
community['data']['state']['nodes'] = get_router_count_by_community(
routers, community)
community['data']['state']['lastchange'] = datetime.datetime.utcnow() \
.isoformat() + 'Z'
with open(os.path.join(output_dir,
community['id'] + '.json'),
'w', encoding='utf-8') as json_file:
json.dump(community['data'], json_file, indent=4, sort_keys=True,
ensure_ascii=False)
if __name__ == '__main__':
if len(sys.argv) < 2:
sys.exit('Please specify a output directory for the community files.')
OUTPUT_DIRECTORY = sys.argv[1]
if not os.path.exists(OUTPUT_DIRECTORY):
os.mkdir(OUTPUT_DIRECTORY)
update_community_files(
'https://monitoring.freifunk-franken.de/api/nodelist',
'communitys_franken.json', OUTPUT_DIRECTORY)