forked from kabegeo/oc_car
-
Notifications
You must be signed in to change notification settings - Fork 0
/
oc_car.sh
383 lines (328 loc) · 14.4 KB
/
oc_car.sh
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
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
#!/bin/bash
#
# Version 0.5
# Aufruf des Scripts:
# z.B.: Script Inputfile Radius in km user
# ./oc_car.sh route.gpx 1.5 ka_be
# Alle Parameter MÜSSEN angegeben werden!!!
# Eine Route kann man sich ohne Anmeldung z.B. bei openrouteservice.org/?lang=de# erzeugen und als GPX-Datei speichern.
# Für dieses Script müssen gpsbabel und BC installiert sein.
# Wenn sendemail installiert ist, kann eine Mail mit angehängter GPX-Datei versendet werden.
# System ermitteln.
case "$(uname -s)" in
CYGWIN*|MINGW*) isWindows=true;;
*) isWindows=false
esac
# Config-Datei prüfen.
if [ -f ./oc_car.conf ] ; then
echo " "
else {
# Schreibe Initialwerte in config-Datei
echo "ocUser=\"User\""
echo "Radius=2"
echo "Start=\"Stuttgart\""
if [ "${isWindows}" = true ]; then
echo "Ziel=\"Muenchen\""
else
echo "Ziel=\"München\""
fi
echo "Arten=\"alle\""
echo "Difficulty=\"1-5\""
echo "Terrain=\"1-5\""
echo "sender=\"[email protected]\""
echo "receiver=\"[email protected]\""
echo "tls=\"tls=yes\""
echo "smtp=\"smtp.gmail.com:587\""
echo "mailuser=\"[email protected]\""
echo "mailpassword=\"password\""
echo "subject=\"oc_car.sh - Die GPX-Datei für Deine Route\""
echo "body=\"Die GPX-Datei für Deine Route!\""
} >> ./oc_car.conf
fi
# Externe Variablen einbinden.
source oc_car.conf
# Überprüfen der GPX-Datei, bzw. ob eine GPX-Datei im Aufruf enthalten war.
input=$1
if gpsbabel -i gpx -f "$input" -o gpx -F - > /dev/null; then
# echo "GPX-Datei ist gültig"
gpxok=true
else
# echo "GPX-Datei ist ungültig! Es wird ein Route über Start/Ziel erstellt."
gpxok=false
fi
# Menü
while true
do
clear
echo "Folgende Parameter wurden in der Konfigurationsdatei gefunden:"
echo "[U]ser: ${ocUser}"
echo "[R]adius: ${Radius}"
echo "[S]tart: ${Start}"
echo "[Z]iel: ${Ziel}"
echo "[A]rten: ${Arten}"
echo "[D]ifficulty: ${Difficulty}"
echo "[T]errain: ${Terrain}"
echo "[B]etreffzeile: ${subject}"
echo "[M]ail-Text: ${body}"
echo "Für den E-Mail-Versand werden die in oc_car.conf hinterlegten Parameter genutzt."
echo ""
if [ "${gpxok}" = true ]; then
echo "Es wurde eine gültige GPX-Datei übergeben. Es wird keine neue Route berechnet."
else
echo "Es wurde keine gültige GPX-Datei übergeben. Es wird eine neue Route berechnet."
fi
echo ""
echo "Sollen Parameter geändert werden? [N]ein, [E]nde -> [U,R,S,Z,A,D,T,B,M,N,E]"
read -r answer
case $answer in
# Eingabe des Benutzernamens.
u*|U*) echo "Bitte neuen Benutzer eingeben:";
read -r ocUser;
grep -v ocUser oc_car.conf > tempdatei;
mv tempdatei oc_car.conf;
echo "ocUser=\"${ocUser}\"" >> oc_car.conf;;
# Eingabe des Radius.
r*|R*) echo "Bitte neuen Radius eingeben:";
read -r Radius;
grep -v Radius oc_car.conf > tempdatei;
mv tempdatei oc_car.conf;
echo "Radius=${Radius}" >> oc_car.conf;;
# Eingabe des Starts.
s*|S*) echo "Bitte neuen Start eingeben:";
read -r Start;
if [ "${isWindows}" = true ]; then
# Umlaute ersetzen.
Start="$( echo "${Start}" | sed -e 's/Ä/Ae/g' -e 's/Ö/Oe/g' -e 's/Ü/Ue/g' -e 's/ä/ae/g' -e 's/ö/oe/g' -e 's/ü/ue/g' -e 's/ß/ss/g' )"
fi
# Leerzeichen durch Plus ersetzen.
Start="${Start// /+}"
grep -v Start oc_car.conf > tempdatei;
mv tempdatei oc_car.conf;
echo "Start=\"${Start}\"" >> oc_car.conf;;
# Eingabe des Ziels.
z*|Z*) echo "Bitte neues Ziel eingeben:";
read -r Ziel;
if [ "${isWindows}" = true ]; then
# Umlaute ersetzen.
Ziel="$( echo "${Ziel}" | sed -e 's/Ä/Ae/g' -e 's/Ö/Oe/g' -e 's/Ü/Ue/g' -e 's/ä/ae/g' -e 's/ö/oe/g' -e 's/ü/ue/g' -e 's/ß/ss/g' )"
fi
# Leerzeichen durch Plus ersetzen.
Ziel="${Ziel// /+}"
grep -v Ziel oc_car.conf > tempdatei;
mv tempdatei oc_car.conf;
echo "Ziel=\"${Ziel}\"" >> oc_car.conf;;
# Eingabe der Cachetypen.
a*|A*) echo "Bitte die gewünschten Cachetypen durch Kommas getrennt eingeben (möglich: alle, Traditional, Multi, Quiz, Virtual, Event, Webcam, Moving, Math/Physics, Drive-In, Other):";
read -r Arten;
Arten=$( echo "${Arten}" | sed -e 's/,/|/g' -e 's/ //g' )
grep -v Arten oc_car.conf > tempdatei;
mv tempdatei oc_car.conf;
echo "Arten=\"${Arten}\"" >> oc_car.conf;;
# Eingabe der Schwierigkeitswertung.
d*|D*) echo "Bitte neuen Schwierigkeitsbereich (nur Ganzzahlen von 1 bis 5, z. B. 1-3) eingeben:";
read -r Difficulty;
Difficulty="${Difficulty// /}"
grep -v Difficulty oc_car.conf > tempdatei;
mv tempdatei oc_car.conf;
echo "Difficulty=\"${Difficulty}\"" >> oc_car.conf;;
# Eingabe der Geländewertung.
t*|T*) echo "Bitte neuen Geländebereich (nur Ganzzahlen von 1 bis 5, z. B. 1-3) eingeben:";
read -r Terrain;
Terrain="${Terrain// /}"
grep -v Terrain oc_car.conf > tempdatei;
mv tempdatei oc_car.conf;
echo "Terrain=\"${Terrain}\"" >> oc_car.conf;;
# Eingabe des E-Mail-Betreffs.
b*|B*) echo "Bitte neuen E-Mail-Betreff eingeben:";
read -r subject;
grep -v subject oc_car.conf > tempdatei;
mv tempdatei oc_car.conf;
echo "subject=\"${subject}\"" >> oc_car.conf;;
# Eingabe des E-Mail-Textes.
m*|M*) echo "Bitte neuen E-Mail-Text eingeben:";
read -r body;
grep -v body oc_car.conf > tempdatei;
mv tempdatei oc_car.conf;
echo "body=\"${body}\"" >> oc_car.conf;;
# Keine Änderung gewünscht.
n*|N*) echo "";
break;;
# Abbrechen.
e*|E*) clear;
exit;;
# Unbekannte Option -> Fehler.
*) echo Das war wohl nichts;;
esac
done
# Bildschirminhalt löschen.
clear
echo "Opencaching.de - Caches auf Route"
# Benutzer-ID ermitteln.
UUID=$( curl -s "https://www.opencaching.de/okapi/services/users/by_username?username=${ocUser}&fields=uuid&consumer_key=8YV657YqzqDcVC3QC9wM" )
# Überprüfen der Benutzer-ID.
if [ "${UUID:0:5}" == "{\"err" ]; then
echo "Benutzer nicht gefunden! Bitte Aufrufparameter prüfen -> z.B. ./oc_car.sh route.gpx 1.5 ka_be"
exit
fi
echo "Benutzer wurde gefunden."
# Abruf der Route.
if [ "${gpxok}" = false ]; then
# Keine gültige GPX-Datei übergeben -> Abruf der Route.
# Koordinaten von Openstreetmap herunterladen.
# `-s` = silent mode.
StartJson="$( curl -s "https://nominatim.openstreetmap.org/search?q=$Start&format=json" )"
ZielJson="$( curl -s "https://nominatim.openstreetmap.org/search?q=$Ziel&format=json" )"
# Mit JSON.sh verarbeiten.
StartJson="$( echo "${StartJson}" | ./JSON.sh )"
ZielJson="$( echo "${ZielJson}" | ./JSON.sh )"
# Zuerst suche ich in der Variable eine Zeile mit [0,"lat"] bzw. [0,"lon"], dann entferne ich dies zusammen mit den
# Anführungszeichen, um den Koordinatenwert zu erhalten.
latS="$(awk '{print $1}' <<< "$(echo "$StartJson" | grep '\[0,"lat"\]' | sed -e 's/\[0,"lat"\]//' -e 's/"//g')")"
lngS="$(awk '{print $1}' <<< "$(echo "$StartJson" | grep '\[0,"lon"\]' | sed -e 's/\[0,"lon"\]//' -e 's/"//g')")"
echo "lng:${lngS}"
echo "lat:${latS}"
latZ="$(awk '{print $1}' <<< "$(echo "$ZielJson" | grep '\[0,"lat"\]' | sed -e 's/\[0,"lat"\]//' -e 's/"//g')")"
lngZ="$(awk '{print $1}' <<< "$(echo "$ZielJson" | grep '\[0,"lon"\]' | sed -e 's/\[0,"lon"\]//' -e 's/"//g')")"
echo "lng:${lngZ}"
echo "lat:${latZ}"
# Die Route wird über YourNavigation abgerufen und in die Datei route.kml gespeichert.
curl -s "http://www.yournavigation.org/api/1.0/gosmore.php?flat=${latS}&flon=${lngS}&tlat=${latZ}&tlon=${lngZ}&v=motorcar&fast=1" > ./route.kml
# Überprüfen der GPX-Datei (konvertierte KML-Datei).
gpsbabel -i kml -f route.kml -o gpx -F route.gpx
if gpsbabel -i gpx -f route.gpx -o gpx -F - > /dev/null; then
echo "GPX-Datei ist gültig"
else
echo "GPX-Datei ist ungültig! Der Download der Route ist fehlgeschlagen."
exit
fi
fi
# Überprüfen des Radius.
if [ "$(echo " ${Radius} > 0" | bc)" -eq 1 ]; then
if [ "$(echo " ${Radius} < 10.1" | bc)" -eq 1 ]; then
echo "Radius ist ok"
else
echo "Radius muss zwischen 0 und 10.1 liegen! Bitte Parameter prüfen."
exit
fi
else
echo "Radius muss zwischen 0 und 10.1 liegen! Bitte Parameter prüfen."
exit
fi
# Rechts 2 Zeichen abschneiden.
UUID=${UUID%??}
# Links 9 Zeichen abschneiden.
UUID=${UUID#?????????}
echo
# Error und distance sind Parameter für die Bearbeitung der Route und zum Festlegen der Koordinaten für die jeweilige
# Umkreissuche.
# circle ist die maximale Breite des Korridors.
# Bei einem Verhältnis error/circle ~1/4 und distance/circle ~ 5/4 ergibt dass eine Mindestabdeckung von ca. 2/3 von
# circle.
error="0$( echo "scale=2; ${Radius} / 4" | bc )k" # Douglas-Peucker tolerance
distance="0$(echo "scale=2; ${Radius} / 4 * 5" | bc)k" # interpolation distance
circle=$Radius # Suchradius in km
echo "Der max. Abstand zur festgelegten Route beträgt $(echo "scale=3; ${circle} / 2" | bc)km."
echo "Alle ${distance}m wird eine neue OC.de-Abfrage durchgeführt."
echo "Zur Glättung der Route wird der Wert ${error}m genutzt."
echo
echo "Das kann jetzt ein paar Sekunden dauern..."
# gpsbabel zum Glätten und Berechnen der Koordinaten für die jeweilige Umkreissuche.
if [ "${gpxok}" == true ]; then
searchargs=$(
gpsbabel -i gpx -f "$input" -x "simplify,crosstrack,error=$error" -o gpx -F - |
gpsbabel -i gpx -f - -x "interpolate,distance=$distance" -o csv -F - |
tr ',' ' ' |
awk '{printf("%.3f,%.3f|",$1,$2)}'
)
else
searchargs=$(
gpsbabel -i gpx -f route.gpx -x "simplify,crosstrack,error=$error" -o gpx -F - |
gpsbabel -i gpx -f - -x "interpolate,distance=$distance" -o csv -F - |
tr ',' ' ' |
awk '{printf("%.3f,%.3f|",$1,$2)}'
)
fi
echo "Punkte auf der Route wurden berechnet!"
echo
echo "An diesen Punkten wird mit einem Radius von ${circle}km nach OC-Dosen gesucht:"
echo "Das kann jetzt ein paar Sekunden dauern..."
echo
# Hier wird aus dem Format Lat,Lon|Lat,Lon -> Lat|Lon,Lat|Lon.
b="${searchargs//|/a}"
c="${b//,/|}"
d="${c//a/,}"
# Hier werden aus dem String die einzelnen Koordinatenpaare in ein Array geschrieben.
IFS=',' read -r -a array <<< "${d}"
for index in "${!array[@]}"; do
echo -n
done
# Variablen festlegen für die Fortschrittsanzeige.
coords="${#array[@]}"
echo " Prozent - Anzahl Listings"
echo
prozent=0
# Hier finden die einzelnen Abfragen statt, der Consumer_key kann bei http://www.opencaching.de/okapi/signup.html
# besorgt werden.
ArtenGross=$(echo "${Arten}" | tr "[:lower:]" "[:upper:]") # in Großbuchstaben umwandeln
for index in "${!array[@]}"; do
# Arten anhängen.
if [ "${ArtenGross}" == "ALLE" ]; then
nearestJson=$( curl -s "https://www.opencaching.de/okapi/services/caches/search/nearest?center=${array[index]}&radius=${circle}&difficulty=${Difficulty}&terrain=${Terrain}&status=Available&consumer_key=8YV657YqzqDcVC3QC9wM")
else
nearestJson=$( curl -s "https://www.opencaching.de/okapi/services/caches/search/nearest?center=${array[index]}&radius=${circle}&type=${Arten}&difficulty=${Difficulty}&terrain=${Terrain}&status=Available&consumer_key=8YV657YqzqDcVC3QC9wM" )
fi
# Wenn weniger als 30 Zeichen zurückkommen, war in diesem Bereich keine Dose versteckt.
if [ ${#nearestJson} -lt 30 ]; then
# Nichts tun.
:
else
# Ansonsten den Ausgabestring bearbeiten.
# Rechts 16 Zeichen abschneiden (`"],"more":false}`).
nearestJson=${nearestJson%????????????????}
# Links 13 Zeichen abschneiden (`{"results":["`).
nearestJson=${nearestJson#?????????????}
# Hier werden die " entfernt und das Komma gegen ein Leerzeichen getauscht.
aktuelleCodes="${nearestJson//\"/}"
aktuelleCodes="${aktuelleCodes//,/\ }"
aktuelleCodes="${aktuelleCodes} "
# In der Variable $alle werden alle ermittelten OC-Codes gespeichert.
alle="${alle}${aktuelleCodes} "
alle="${alle%?}"
fi
# Fortschritt.
anzahl="$( echo "${alle}" | wc -w )"
prozent=$( echo "scale=9;${prozent} + 100 / ${coords}" | bc)
echo -en "\r${prozent} % - ${anzahl}"
done
echo
# Hier werden Duplikate aus dem String gefiltert.
alleGefiltert="$( echo "${alle}" | xargs -n 1 | sort -u | xargs )"
echo -n "Gefundene Listings ohne Duplikate: "
zahl=$( echo "${alleGefiltert}" | wc -w )
echo "${zahl}"
# Anzahl Abrufe zu je 500 bestimmen.
loop=$(( zahl / 500 ))
# Prüfen, ob `sendemail` verfügbar ist.
hasSendemail=false
if [ -z "$(which sendemail)" ]; then
hasSendemail=true
fi
for (( c=0; c<=loop; c++ )); do
# `spalte` entspricht dem Startindex der aktuellen Iteration.
spalte=$(( (c * 500) + 1 ))
# Der aktuelle Teil der Codes.
codes=$( echo "${alleGefiltert}" | cut -d " " -f "${spalte}-$(( spalte+499 ))" )
# Die auszugebende Geocache-GPX-Datei bestimmen -> Format `(YYMMDD-HHMMSS)PQ.gpx`.
output="$(date "+%y%m%d-%H%M%S")PQ.gpx"
# Jetzt werden die | zwischen die OC-Codes eingefügt und der OKAPI-Aufruf durchgeführt.
codes="${codes//\ /|}"
gpxAusgabe=$( curl -s "https://www.opencaching.de/okapi/services/caches/formatters/gpx?cache_codes=${codes}&consumer_key=8YV657YqzqDcVC3QC9wM&ns_ground=true&latest_logs=true&mark_found=true&user_uuid=$UUID" )
echo "${gpxAusgabe}" >> "$output"
echo "Die Datei ${output} wird hier im Verzeichnis abgelegt und per E-Mail versendet."
# Per E-Mail versenden.
# shellcheck disable=SC2154 # Defined from sourced file.
if [ "${hasSendemail}" = true ]; then
sendemail -f "$sender" -t "$receiver" -o "$tls" -s "$smtp" -xu "$mailuser" -xp "$mailpassword" -u $"${subject} GPX $(( c + 1 )) von $(( loop + 1 ))" -m "${body}" -a "${output}"
fi
done
exit