diff --git a/noise/public/javascripts/chart_utilities.js b/noise/public/javascripts/chart_utilities.js index aa4ce2b..40770f4 100644 --- a/noise/public/javascripts/chart_utilities.js +++ b/noise/public/javascripts/chart_utilities.js @@ -255,14 +255,17 @@ export const addAddress = async (sid) => { } } +// liefert {coords: [lat, lon], err: null} oder {coords: null, err: }. +// 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 diff --git a/noise/public/javascripts/global.js b/noise/public/javascripts/global.js index d7edd60..28345f0 100644 --- a/noise/public/javascripts/global.js +++ b/noise/public/javascripts/global.js @@ -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) { diff --git a/noise/routes/api.js b/noise/routes/api.js index 24c9202..c3df57f 100644 --- a/noise/routes/api.js +++ b/noise/routes/api.js @@ -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) { diff --git a/sensorapi/actions/getaddress.js b/sensorapi/actions/getaddress.js index eecf128..84e4e40 100644 --- a/sensorapi/actions/getaddress.js +++ b/sensorapi/actions/getaddress.js @@ -6,17 +6,27 @@ import { response } from "express" const NOMINATIM_URL = `https://nominatim.openstreetmap.org/reverse?lat=${'xx'}&lon=${'yy'}&format=json` const NOMINATIM_CITY_URL = `https://nominatim.openstreetmap.org/?q="${'xx'}"&format=json` +// Nominatim verlangt laut Nutzungsbedingungen einen eigenen User-Agent und +// beantwortet den Default von axios ('axios/1.x') mit 403. +const NOMINATIM_UA = 'laermsensor-stack (rxf@gmx.de)' export const getCityCoords = async (params) => { let ret = {coords: [], city: params.city, err: null} let url = NOMINATIM_CITY_URL.replace('xx', params.city) // let url = 'https://nominatim.openstreetmap.org/?q="K%C3%B6ln"&format=json' try { - const response = await axios(url) + const response = await axios(encodeURI(url), { + headers: { + 'User-Agent': NOMINATIM_UA + } + }) if (response.status !== 200) { - return returnOnError(ret, 'RESPSTATUS', getCityCoord.name, response.status) + return returnOnError(ret, 'RESPSTATUS', getCityCoords.name, response.status) } - ret.coords = [response.data[0].lat,response.data[0].lon] + if (!response.data.length) { // Stadt nicht gefunden + return returnOnError(ret, 'ENOCITY', getCityCoords.name, params.city) + } + ret.coords = [parseFloat(response.data[0].lat), parseFloat(response.data[0].lon)] logit(JSON.stringify(ret.coords)) } catch (e) { return returnOnError(ret, e, getCityCoords.name) @@ -35,7 +45,7 @@ export const getAddress = async (params) => { try { const response = await axios(encodeURI(url),{ headers: { - 'User-Agent': 'Firefox 132.0.1' + 'User-Agent': NOMINATIM_UA } }); if (response.status !== 200) { diff --git a/sensorapi/locales/de/translation.json b/sensorapi/locales/de/translation.json index bd7b225..ffa9399 100644 --- a/sensorapi/locales/de/translation.json +++ b/sensorapi/locales/de/translation.json @@ -12,5 +12,6 @@ "SYNTAXURL": "Syntax Fehler beim Aufruf der URL", "WRONGTYPE": "Sensor xxx ist kein yyy Sensor", "NOLASTDATES": "Probleme bein abholen der letzten Daten", - "NOPROPSFOUND": "Properties Collection nicht gefunden" + "NOPROPSFOUND": "Properties Collection nicht gefunden", + "ENOCITY": "Ort \"xxx\" nicht gefunden" } diff --git a/sensorapi/locales/en/translation.json b/sensorapi/locales/en/translation.json index d701d6d..f4d9bd0 100644 --- a/sensorapi/locales/en/translation.json +++ b/sensorapi/locales/en/translation.json @@ -12,5 +12,6 @@ "SYNTAXURL": "Syntax error in calling url!", "WRONGTYPE": "Sensor xxx is not of type yyy", "NOLASTDATES": "Problems fetching last dates from database", - "NOPROPSFOUND": "Properties collection not found" + "NOPROPSFOUND": "Properties collection not found", + "ENOCITY": "City 'xxx' not found" }