Stadtsuche in den Einstellungen repariert (graue Karte)

Wer auf dem Kartenreiter die Einstellungen oeffnete und eine Stadt eingab,
bekam danach nur noch ein graues Fenster. Drei Fehler wirkten zusammen:

1. getCityCoords() rief Nominatim ohne eigenen User-Agent auf. Nominatim
   beantwortet den axios-Default mit 403, und zwar fuer jede Stadt. Die
   Schwesterfunktion getAddress() setzt seit jeher einen User-Agent -
   deshalb funktionierten die Adressen an den Sensoren, nur die
   Stadtsuche nicht. Beide nutzen jetzt dieselbe Konstante.

2. cityCoords() lieferte im Fehlerfall den String "no coordinates". Der
   landete als Kartenzentrum in L.map().setView(), Leaflet warf "Invalid
   LatLng object" - und weil showMap() die alte Karte vorher schon
   entfernt hat, blieb der Container leer. Daher grau statt Fehlermeldung.
   cityCoords() liefert jetzt {coords, err}; schlaegt die Suche fehl,
   bleibt das bisherige Zentrum stehen und der Text wird angezeigt.

3. Der Proxy in noise/routes/api.js kodierte die bereits prozentkodierte
   req.originalUrl ein zweites Mal. 'Goettingen' kam als 'G%c3%b6ttingen'
   an. Das fiel bisher nicht auf, weil schon Punkt 1 alles abfing.

Ausserdem: Tippfehler getCityCoord.name, fehlendes encodeURI bei der
Stadtsuche, Koordinaten als Zahl statt String, und eine eigene Meldung
(ENOCITY), wenn Nominatim den Ort nicht kennt.

Geprueft ueber die volle Kette noise -> sensorapi -> Nominatim:
Stuttgart, Goettingen (Umlaut), Bad Cannstatt (Leerzeichen) liefern
Koordinaten, ein erfundener Ort eine saubere Meldung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-03 15:03:27 +00:00
parent 887399ef85
commit 10cd964ede
6 changed files with 44 additions and 14 deletions
+7 -4
View File
@@ -255,14 +255,17 @@ export const addAddress = async (sid) => {
}
}
// liefert {coords: [lat, lon], err: null} oder {coords: null, err: <Meldung>}.
// Kein Ersatzwert wie frueher "no coordinates": der Aufrufer muss den Fehlschlag
// erkennen koennen, sonst landet ein ungueltiges Zentrum in der Karte und
// Leaflet baut sie nicht mehr auf (graues Fenster).
export const cityCoords = async (city) => {
let url = `/srv/getcitycoords?city=${city}`
let erg = await fetchfromserver(url)
if (!erg.err) {
return erg.coords
} else {
return "no coordinates"
if (erg.err || !Array.isArray(erg.coords) || erg.coords.length !== 2) {
return {coords: null, err: erg.err || `'${city}' ?`}
}
return {coords: erg.coords, err: null}
}
// table to distribute the different charts
+15 -3
View File
@@ -86,6 +86,7 @@ import * as spin from './spinner.js'
// Button 'Save' pressed
document.querySelector('#btnSave').addEventListener('click', async () => {
let curtab = getCurrentTab()
let cityErr = null // Meldung erst nach dem Schliessen des Dialogs zeigen
for(let i = 0; i < setting.length; i++) {
if(setting[i].typ === getCurrentTab()) {
for(let j = 0; j < setting[i].show.length; j++) {
@@ -115,9 +116,17 @@ import * as spin from './spinner.js'
params.datetime = starttime
} else {
const oldCoords = params.center.coords
params.center.coords = await cityCoords(params.center.name)
checkNewCenter(oldCoords, params.center.coords)
localStorage.setItem('centercity',JSON.stringify(params.center))
const erg = await cityCoords(params.center.name)
if (erg.coords === null) {
// Ort nicht aufloesbar: altes Zentrum behalten. Ohne das landet
// ein ungueltiger Wert in setView() und die Karte bleibt grau.
cityErr = erg.err
params.center = JSON.parse(localStorage.getItem('centercity'))
} else {
params.center.coords = erg.coords
checkNewCenter(oldCoords, params.center.coords)
localStorage.setItem('centercity',JSON.stringify(params.center))
}
}
let newlng = document.querySelector('#sellan input:checked').id
let oldlng = localStorage.getItem('curlang')
@@ -129,6 +138,9 @@ import * as spin from './spinner.js'
spin.spinner.spin(spin.spindiv)
await loadAll(params,0, curtab)
spin.spinner.stop()
if (cityErr) {
showError(cityErr)
}
// ToDo:
// Load ALL incl. MAP und LIVE hier, d.h. an loadAll einen zusätzlichen Parameter übergeben
// if(params.sid !== undefined) {
+4 -1
View File
@@ -29,7 +29,10 @@ router.get('/:cmd', async function(req, res, next) {
let url = APIHOST + '/api' + req.originalUrl.slice(4) + `&lng=${lng}`
try {
const response = await axios.get(encodeURI(url) , {
// kein encodeURI: req.originalUrl ist bereits prozentkodiert. Ein zweiter
// Durchlauf macht aus '%C3%B6' ein '%25C3%25B6', und die Gegenseite sieht
// dann den Text 'G%c3%b6ttingen' statt 'Göttingen'.
const response = await axios.get(url , {
headers: {'X-API-Key': API_KEY}
});
if (response.status !== 200) {