aboutsummaryrefslogtreecommitdiffstats
path: root/src/anetz/stations.c
blob: 1b5bc50196628f5d9d6256fd4ac646169f16ae9e (plain)
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

static struct anetz_stations {
	const char	*standort;
	int		kanal21; /* Channel for prefix 21 */
	int		kanal22; /* Channel for prefix 22 (0 = use previous channel) */
	int		kanal23; /* ... */
	int		kanal24;
	int		kanal25;
	const char	*coordinates;
} anetz_stations[] = {
/*	  Standort			Prefix 21..25 	Coorinates */
	{ "Niebuell",			32, 0, 0, 0, 0,	"54o47 08o50" },
	{ "Flensburg",			39, 0, 0, 0, 0,	"54o47 09o26" },
	{ "Schleswig",			35, 0, 0, 0, 0,	"54o31 09o34" },
	{ "Kiel",			36, 0, 0,38, 0,	"54o20 10o08" },
	{ "Toenning",			37, 0, 0, 0, 0,	"54o19 08o57" },
	{ "Heide",			34, 0, 0, 0, 0,	"54o12 09o06" },
	{ "Eutin",			30, 0, 0, 0, 0,	"54o08 10o37" },
	{ "Neumuenster",		32, 0, 0, 0, 0,	"54o04 09o59" },
	{ "Luebeck",			37, 0, 0,42, 0,	"53o52 10o41" },
	{ "Cuxhaven",			30, 0, 0, 0, 0,	"53o52 08o41" },
	{ "Hemmoor",			40, 0, 0, 0, 0,	"53o42 09o08" },
	{ "Ratzeburg",			40, 0, 0, 0, 0,	"53o42 10o45" },
	{ "Hamburg",			39,35,31,41,33,	"53o34 10o00" },
	{ "Bremerhaven",		39, 0, 0,41, 0,	"53o33 08o35" },
	{ "Wilhelmshaven",		36, 0, 0, 0, 0,	"53o31 08o08" },
	{ "Aurich",			32, 0, 0, 0, 0,	"53o28 07o29" },
	{ "Lueneburg",			32, 0, 0, 0, 0,	"53o15 10o25" },
	{ "Leer",			35, 0, 0, 0, 0,	"53o14 07o27" },
	{ "Oldenburg",			30, 0, 0,31, 0,	"53o09 08o13" },
	{ "Rotenburg",			30, 0, 0, 0, 0,	"53o06 09o24" },
	{ "Bremen",			37,44,33,42, 0,	"53o05 08o48" },
	{ "Soltau",			35, 0, 0, 0, 0,	"52o59 09o50" },
	{ "Luechow",			30, 0, 0, 0, 0,	"52o58 11o09" },
	{ "Uelzen",			34, 0, 0, 0, 0,	"52o58 10o33" },
	{ "Werlte",			34, 0, 0, 0, 0,	"52o51 07o41" },
	{ "Hoya",			32, 0, 0, 0, 0,	"52o48 09o08" },
	{ "Lingen",			36, 0, 0, 0, 0,	"52o31 07o19" },
	{ "Berlin",			39,33,35,41, 0,	"52o31 13o23" },
	{ "Wolfsburg",			30, 0, 0, 0, 0,	"52o25 10o47" },
	{ "Hannover",			36,44,33,38, 0,	"52o22 09o43" },
	{ "Osnabrueck",			39, 0, 0,41, 0,	"52o17 08o03" },
	{ "Minden",			30, 0, 0,40, 0,	"52o17 08o55" },
	{ "Braunschweig",		37, 0, 0,42, 0,	"52o16 10o31" },
	{ "Burgsteinfurt",		37, 0, 0, 0, 0,	"52o09 07o21" },
	{ "Bielefeld",			34,33, 0,43, 0,	"52o01 08o31" },
	{ "Alfeld",			39, 0, 0, 0, 0,	"51o59 09o50" },
	{ "Muenster",			32, 0, 0,42, 0,	"51o58 07o38" },
	{ "Kleve",			32, 0,31,38, 0,	"51o47 06o08" },
	{ "Paderborn",			37, 0, 0, 0, 0,	"51o43 08o46" },
	{ "Wesel",			45, 0, 0, 0, 0,	"51o40 06o37" },
	{ "Goettingen",			34, 0, 0, 0, 0,	"51o32 09o56" },
	{ "Dortmund",			36, 0, 31,38,0,	"51o31 07o28" },
	{ "Essen",			34, 0, 0, 0,43,	"51o27 07o01" },
	{ "Duisburg",			39,44,33,41, 0,	"51o26 06o46" },
	{ "Meschede",			35, 0, 0, 0, 0,	"51o21 08o17" },
	{ "Kassel",			32, 0, 0, 0, 0,	"51o19 09o30" },
	{ "Wuppertal",			30, 0, 0, 0,40,	"51o16 07o11" },
	{ "Korbach",			38, 0, 0, 0, 0,	"51o17 08o52" },
	{ "Luedenscheid",		39, 0, 0, 0, 0,	"51o13 07o38" },
	{ "Winterberg",			33, 0, 0, 0, 0,	"51o12 08o31" },
	{ "Duesseldorf",		37, 0, 31,42,0,	"51o14 06o47" },
	{ "Eschwege",			39, 0, 0, 0, 0,	"51o11 10o03" },
	{ "Koeln",			36,35,33,38, 0,	"50o56 06o57" },
	{ "Siegen",			36, 0, 0, 0, 0,	"50o53 08o01" },
	{ "Aachen",			34, 0, 0, 0, 0,	"50o47 06o05" },
	{ "Alsfeld",			36, 0, 0,40, 0,	"50o45 09o16" },
	{ "Bonn",			32, 0, 0,41, 0,	"50o44 07o06" },
	{ "Dillenburg",			42, 0, 0, 0, 0,	"50o44 08o17" },
	{ "Giessen",			34, 0, 0, 0, 0,	"50o35 08o40" },
	{ "Fulda",			30, 0, 0, 0, 0,	"50o33 09o41" },
	{ "Montabaur",			46, 0, 0, 0, 0,	"50o26 07o50" },
	{ "Usingen",			30, 0, 0, 0, 0,	"50o20 08o32" },
	{ "Mayen",			34, 0, 0, 0, 0,	"50o20 07o13" },
	{ "Hof",			39, 0, 0, 0, 0,	"50o19 11o55" },
	{ "Coburg",			35, 0, 0, 0, 0,	"50o16 10o58" },
	{ "Boppard",			39, 31,0, 35,0,	"50o14 07o35" },
	{ "Koblenz",			40, 0, 0, 0, 0,	"50o22 07o36" },
	{ "Pruem",			35, 0, 0, 0, 0,	"50o12 06o25" },
	{ "Gelnhausen",			41, 0, 0, 0, 0,	"50o12 09o10" },
	{ "Wiesbaden",			30, 0, 0, 0,40,	"50o05 08o14" },
	{ "Hanau",			39, 0, 0, 0, 0,	"50o08 08o55" },
	{ "Frankfurt",			37,35,31,42,33,	"50o07 08o41" },
	{ "Schweinfurt",		34, 0, 0, 0, 0,	"50o03 10o14" },
	{ "Aschaffenburg",		45, 0, 0, 0, 0,	"49o58 09o09" },
	{ "Bingen",			36, 0, 0,41, 0,	"49o58 07o54" },
	{ "Bayreuth",			30, 0, 0, 0, 0,	"49o57 11o35" },
	{ "Bernkastel",			37, 0, 0, 0, 0,	"49o55 07o04" },
	{ "Bamberg",			37, 0, 0, 0, 0,	"49o54 10o54" },
	{ "Darmstadt",			32, 0, 0,38, 0,	"49o52 08o39" },
	{ "Marktheidenfeld",		36, 0, 0, 0, 0,	"49o51 09o36" },
	{ "Wuerzburg",			39, 0, 0,44, 0,	"49o47 09o56" },
	{ "Pegnitz",			34, 0, 0, 0, 0,	"49o45 11o34" },
	{ "Trier",			39, 0, 0, 0, 0,	"49o45 06o38" },
	{ "Kitzingen",			32, 0, 0, 0, 0,	"49o44 10o10" },
	{ "Idar-Oberstein",		32, 0, 0, 0, 0,	"49o43 07o19" },
	{ "Lindenfels",			34, 0, 0, 0, 0,	"49o41 08o47" },
	{ "Weiden",			32, 0, 0, 0, 0,	"49o40 12o09" },
	{ "Mannheim",			39,35,44,41, 0,	"49o29 08o28" },
	{ "Fuerth",			44, 0, 0, 0, 0,	"49o28 11o00" },
	{ "Kaiserslautern",		34, 0, 0,43, 0,	"49o27 07o46" },
	{ "Nuernberg",			39, 0, 33,41,0,	"49o27 11o05" },
	{ "Heidelberg",			37, 0, 0,42, 0,	"49o25 08o43" },
	{ "Ansbach",			30, 0, 0, 0, 0,	"49o18 10o35" },
	{ "Neumarkt",			35, 0, 0, 0, 0,	"49o17 11o28" },
	{ "Saarbruecken",		30, 0, 0,40, 0,	"49o14 07o00" },
	{ "Heilbronn",			32, 0, 0,43, 0,	"49o09 09o13" },
	{ "Schwaebisch Hall",		41, 0, 0, 0, 0,	"49o07 09o44" },
	{ "Weissenburg",		36, 0, 0, 0, 0,	"49o02 10o58" },
	{ "Regensburg",			30, 0, 0, 0, 0,	"49o01 12o05" },
	{ "Karlsruhe",			30, 0, 0, 0,40,	"49o01 08o24" },
	{ "Pforzheim",			46, 0, 0, 0, 0,	"48o54 08o43" },
	{ "Deggendorf",			37, 0, 0, 0, 0,	"48o50 12o58" },
	{ "Schwaebisch Gmuend",		34, 0, 0, 0, 0,	"48o48 09o48" },
	{ "Stuttgart",			35,44,33,38,40,	"48o47 09o11" },
	{ "Calw",			31, 0, 0, 0, 0,	"48o43 08o44" },
	{ "Geislingen",			35, 0, 0, 0, 0,	"48o37 09o50" },
	{ "Passau",			36, 0, 0, 0, 0,	"48o34 13o28" },
	{ "Landshut",			34, 0, 0, 0, 0,	"48o32 12o09" },
	{ "Pfaffenhofen",		32, 0, 0, 0, 0,	"48o32 11o31" },
	{ "Tuebingen",			37, 0, 0, 0, 0,	"48o31 09o03" },
	{ "Offenburg",			32, 0, 0,38, 0,	"48o28 07o56" },
	{ "Freudenstadt",		39, 0, 0, 0, 0,	"48o28 08o25" },
	{ "Pfarrkirchen",		35, 0, 0, 0, 0,	"48o25 12o55" },
	{ "Ulm",			39, 0, 0,41, 0,	"48o24 09o59" },
	{ "Augsburg",			37, 0, 0,42, 0,	"48o22 10o54" },
	{ "Rottweil",			34, 0, 0,43, 0,	"48o10 08o37" },
	{ "Riedlingen",			33, 0, 0, 0, 0,	"48o09 09o28" },
	{ "Muenchen",			39,35,33,41,44,	"48o08 11o34" },
	{ "Wasserburg",			36, 0, 0,42, 0,	"48o03 12o14" },
	{ "Freiburg",			37, 0, 0,31, 0,	"47o59 07o51" },
	{ "Donaueschingen",		37, 0, 0, 0, 0,	"47o57 08o30" },
	{ "Neustadt",			30, 0, 0, 0, 0,	"47o55 08o13" },
	{ "Weilheim",			30, 0, 0, 0, 0,	"47o50 11o09" },
	{ "Ravensburg",			30, 0, 0, 0, 0,	"47o47 09o37" },
	{ "Singen",			31, 0, 0, 0, 0,	"47o46 08o50" },
	{ "Bad Toelz",			37, 0, 0, 0, 0,	"47o46 11o33" },
	{ "Kempten",			34, 0, 0,43, 0,	"47o44 10o19" },
	{ "Bad Reichenhall",		41, 0, 0, 0, 0,	"47o43 12o53" },
	{ "Loerrach",			44, 0, 0, 0, 0,	"47o37 07o40" },
	{ "Saeckingen",			34, 0, 0, 0, 0,	"47o33 07o57" },
	{ "Garmisch-Partenkirchen",	36, 0, 0, 0, 0,	"47o30 11o05" },
	{ NULL, 0, 0, 0, 0, 0, NULL }
};

double lat_from_coordinates(const char *string)
{
	if (strlen(string) != 11)
		abort();
	if (string[0] < '0' && string[0] > '9')
		abort();
	if (string[1] < '0' && string[1] > '9')
		abort();
	if (string[2] != 'o')
		abort();
	if (string[3] < '0' && string[3] > '9')
		abort();
	if (string[4] < '0' && string[4] > '9')
		abort();

	return	(double)(string[0] - '0') * 10.0 +
		(double)(string[1] - '0') +
		(double)(string[3] - '0') / 6.0 +
		(double)(string[4] - '0') / 60.0;
}

double lon_from_coordinates(const char *string)
{
	if (strlen(string) != 11)
		abort();
	if (string[6] < '0' && string[6] > '9')
		abort();
	if (string[7] < '0' && string[7] > '9')
		abort();
	if (string[8] != 'o')
		abort();
	if (string[9] < '0' && string[9] > '9')
		abort();
	if (string[10] < '0' && string[10] > '9')
		abort();

	return	(double)(string[6] - '0') * 10.0 +
		(double)(string[7] - '0') +
		(double)(string[9] - '0') / 6.0 +
		(double)(string[10] - '0') / 60.0;
}

#define EQUATOR_RADIUS  6378137.0
#define POLE_RADIUS     6356752.314

#define PI              M_PI

void station_list(void)
{
	int i;

	printf("List of all base stations:\n");
	for (i = 0; anetz_stations[i].standort; i++) {
		printf("%s (%.2f° N %.2f° E)\n", anetz_stations[i].standort, lat_from_coordinates(anetz_stations[i].coordinates), lon_from_coordinates(anetz_stations[i].coordinates));
	}
}

/* convert geo coordinates (lon/lat) to space coordinates in meters (x/y/z) */
static void geo2space(double *x, double *y, double *z, double lat, double lon)
{
	*z = sin(lat / 180.0 * PI) * POLE_RADIUS;
	*x = sin(lon / 180.0 * PI) * cos(lat / 180.0 * PI) * EQUATOR_RADIUS;
	*y = -cos(lon / 180.0 * PI) * cos(lat / 180.0 * PI) * EQUATOR_RADIUS;
}

/* calculate distance */
static double distinspace(double x1, double y1, double z1, double x2, double y2, double z2)
{
	double x = x1 - x2;
	double y = y1 - y2;
	double z = z1 - z2;

	return sqrt(x * x + y * y + z * z);
}


int get_station_by_coordinates(double lat, double lon)
{
	double dist, min = 0.0;
	int i, min_i = 0;
	double x, y, z;
	double s_lat, s_lon;
	double s_x, s_y, s_z;
	int kanal[5];

	geo2space(&x, &y, &z, lat, lon);

	for (i = 0; anetz_stations[i].standort; i++) {
		s_lat = lat_from_coordinates(anetz_stations[i].coordinates);
		s_lon = lon_from_coordinates(anetz_stations[i].coordinates);
		geo2space(&s_x, &s_y, &s_z, s_lat, s_lon);
		dist = distinspace(x, y, z, s_x, s_y, s_z);
		if (i == 0 || dist < min) {
			min = dist;
			min_i = i;
		}
	}

	/* don't allow distance more than 100KM */
	if (min > 100000) {
		fprintf(stderr, "Given coordinates are more than 100 km away from base station.\n");
		return 0;
	}
	kanal[0] = anetz_stations[min_i].kanal21;
	kanal[1] = anetz_stations[min_i].kanal22;
	kanal[2] = anetz_stations[min_i].kanal23;
	kanal[3] = anetz_stations[min_i].kanal24;
	kanal[4] = anetz_stations[min_i].kanal25;

	for (i = 0; i < 5; i++) {
		if (i && kanal[i] == 0)
			kanal[i] = kanal[i - 1];
	}

	printf("Closest base station: %s (distance = %.2f km)\n", anetz_stations[min_i].standort, min / 1000.0);
	printf("Frequencies allocated in your area were:\n");
	for (i = 0; i < 5; i++)
		printf("  Channel %d for phone numbers '%dxxxxx'\n", kanal[i], i + 21);

	return 0;
}