0

I am currently working on a weather station that gets data from OpenWeatherMap's API every 10 minutes.

Every 10 seconds the temperature is published via MQTT in the topic 'local/temperature', so that other systems (for example a heater or air conditioner) can do further actions depending on the temperature.

Every 10 minutes, parallel to the new data retrieval, the weather operations are also published, also via MQTT.

Publishing the data every 10 seconds is a requirement of the project, but not important for this case.

The problem I'm stuck on is this: My request to the API of OWM is done in an extra file, which contains a function that should return the data as an object. At the same time the data is stored in a file, so that in case of a network failure the last local status is saved and can still be used.

I already write into the file, the 'reading when offline' functionality will be added later on. I have also noticed that the assembleURL() function is actually unnecessary, but I haven't changed that yet.

I'm still relatively new in JavaScript / Nodejs, but I already have experience in Java and Python, so it may be that I have mixed in something from Java by mistake.

Can someone please explain to me why the object I return in openWeatherMapCall.js is undefined? I'm thankful for every hint.

My file weather-station.js that calls the function getData in openWeatherMapCall.js:

const mqtt = require('mqtt');
const owm = require('./lib/openWeatherMapCall');
const client = mqtt.connect('mqtt://localhost:1885');
const fs = require('fs');
const config = require('../config/config.json');
const owmConfig = config.owm;

let weatherData = owm.getData(owmConfig.city, owmConfig.owmapikey, owmConfig.lang, "metric");
console.log(weatherData); // -> it says undefined


setInterval(_ => {
    weatherData = owm.getData(owmConfig.city, owmConfig.owmapikey, owmConfig.lang, "metric");
    client.publish("local/condition", toString(weatherData.weatherID));
    console.log('successful publish of wID ' + weatherData.weatherID);
}, 600000); //10 min

setInterval(_ => {
    client.publish("local/temperature", toString(weatherData.celsius));
    console.log('successful publish of ' + weatherData.celsius + ' celsius');
    }, 30000); //10 sec

My OWM API call as openWeatherMapCall.js:

const fetch = require('node-fetch');
const fs = require('fs');
const util = require("util");

function assembleURL (city, apiKey, lang, units){
    let url = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "&units=" + units + "&lang=" + lang + "&appid=" + apiKey;
    console.log("url: " + url);
    return url;
}
function getData(city, apiKey, lang, units){
let url = assembleURL(city, apiKey, lang, units )
    fetch(url)
        .then(function(resp) { return resp.json() }) // Convert data to json
        .then(function(data) {
            var currentWeather = {
                weather: data.weather[0].description,
                weatherID: data.weather[0].id,
                celsius: Math.round(parseFloat(data.main.temp)),
                wind: data.wind.speed,
                location: data.name
            };
            let toString = JSON.stringify(currentWeather);
            fs.writeFile('../config/weather.json', toString, err => {
                if (err) {
                    console.log('Error while writing', err)
                } else {
                    console.log('Successful write')
                }
            })
            return currentWeather;
        })
        .catch( err => {
            console.log('caught it!',err);

        });
}
module.exports = {getData};
Abbas Hosseini
  • 1,545
  • 8
  • 21
Drogo
  • 3
  • 1
  • Does this answer your question? [JS Fetch API access return value](https://stackoverflow.com/questions/50417982/js-fetch-api-access-return-value/50418166) – jarmod Jan 02 '21 at 18:10
  • 1
    Where is the returned object undefined? `I'm still relatively new in JavaScript` doesnt really mean anything. Anyone cant get undefined. So where is yours? – GetSet Jan 02 '21 at 18:10
  • @GetSet the undefined happens after fetch the url and putting the received data into the object 'currentWeather'. – Drogo Jan 02 '21 at 18:18
  • @jarmod thank you for the further information. I am realizing, that I have to read more about asynchronous functions, I guess the problem is lying somewhere there. – Drogo Jan 02 '21 at 18:20
  • A key part of understanding what's going on here is to understand why your `getData()` function returns undefined. First, the getData function doesn't actually explicitly return any value at all. "How can that be? It returns currentWeather." you might say. Actually, no it doesn't. The line of code that returns currentWeather is actually inside an interior, unnamed (anonymous) function that is declared `function(data) ...`. So currentWeather is the return value of that inner function. Your outer getData function has no return statement, so JavaScript implicitly returns undefined. – jarmod Jan 02 '21 at 18:26
  • ah ok, so i have to "return" `fetch(url)` as well as the actually object `currentWeather`? So as described in the answer from Naren? I'm thankful for your explaining comment, i like to understand the solving of my problem instead of just put the solution in. – Drogo Jan 02 '21 at 18:35

1 Answers1

2

Return fetch response from getData and use then on owm.getData as fetch returns a Promise.

function getData(city, apiKey, lang, units){
    let url = assembleURL(city, apiKey, lang, units )
    return fetch(url)....
}

And

owm.getData(owmConfig.city, owmConfig.owmapikey, owmConfig.lang, "metric").then((weatherData) => {
 console.log(weatherData)
});
Naren
  • 4,152
  • 3
  • 17
  • 28