const axios = require('axios') const _ = require('lodash') // Constants // TODO: Automatically retrieve dates via aviable Data from database and get rid of "random" dates const rangeStartDate = '2019-01-01' // If no date is given, this date will be used as startDate const rangeEndDate = '2019-12-31'// If no date is given, this date will be used as endDate // TODO: call method periodically, not over API (fine for prototyping, tho) module.exports = async (dbConn, startDate = rangeStartDate, endDate = rangeEndDate) => { console.log('update climate with:', startDate, endDate); const result = await dbConn.query(`SELECT id, region, lon, lat FROM regions`) const climateObject = await Promise.all(result.map(src => { return createClimateObjectFrom(src, startDate, endDate) })) const climateObjectArr = climateObject.reduce((total, element) => total.concat(element), []) await writeToDatabase(dbConn, climateObjectArr) const res = `region_climate update v2 complete. see backend logs for info.` return climateObjectArr } async function createClimateObjectFrom(src, startDate, endDate) { let res try { res = await axios.get( `https://api.meteostat.net/v2/point/daily?lat=${src.lat}&lon=${src.lon}&start=${startDate}&end=${endDate}`, { headers: { "x-api-key": process.env.METEOSTAT_API_KEY_V2 }//, //httpsAgent: agent }) } catch (error) { console.log("error while getting data from meteostat: couldn't find results for following region: ") console.log(src.region,"with coords:",src.lon,src.lat) console.log(error) return [] } if (!res.data.data) { console.log("skipping: no data for station with meteostat_id " + src.meteostat_id + " (" + src.region + ")") return [] } const retVal = res.data.data.map(element => { let result = { region: src.region, region_id: src.id, year: element.date.split("-")[0], month: element.date.split("-")[1], day: element.date.split("-")[2], temperature_mean: element.tavg, temperature_mean_min: element.tmin, temperature_mean_max: element.tmax, precipitation: element.prcp, rain_days: element.prcp > 2 ? 1:0, // More than 2mm => rainday sun_hours: element.tsun/60 } //console.log(result) return result }) return retVal } async function writeToDatabase(dbConn, climateObjArr) { for (const element of climateObjArr) { //console.log(element) try { await dbConn.query(` INSERT INTO region_climate_day (region_id, year, month, day, temperature_mean, temperature_mean_min, temperature_mean_max, precipitation, sun_hours, rain_days) VALUES (${element.region_id}, ${element.year}, ${element.month}, ${element.day}, ${element.temperature_mean}, ${element.temperature_mean_min}, ${element.temperature_mean_max}, ${element.precipitation}, ${element.sun_hours}, ${element.rain_days}) ON DUPLICATE KEY UPDATE temperature_mean = ${element.temperature_mean}, temperature_mean_min = ${element.temperature_mean_min}, temperature_mean_max = ${element.temperature_mean_max}, precipitation = ${element.precipitation}, sun_hours = ${element.sun_hours}, rain_days = ${element.rain_days};`) } catch (error) { if (error.code !== 'ER_DUP_ENTRY') { console.log("element which causes problems: ") console.log(element) console.log("query which causes problems: ") console.log(error) } else { console.log(element.region + ": " + error.sqlMessage) } } } }; /* INSERT INTO region_climate (region_id, YEAR, MONTH, temperature_mean, temperature_mean_min, temperature_mean_max, precipitation, rain_days, sun_hours) SELECT region_id, YEAR, MONTH, ROUND(AVG(temperature_mean),2) AS temperature_mean, MIN(temperature_mean_min) AS temperature_mean_min, MAX(temperature_mean_max) AS temperature_mean_max, ROUND(SUM(precipitation),2) AS precipitation, SUM(rain_days) AS rain_days, SUM(sun_hours) AS sun_hours FROM region_climate_day GROUP BY region_id, YEAR, month */