Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select gas stations #25

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion MMM-Fuel.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Module.register('MMM-Fuel', {
* @property {int} updateInterval - Speed of update.
* @property {string} provider - API provider of the data.
* @property {boolean} toFixed - Flag to show price with only 2 decimals.
* @property {string[]} ids - List of gas stations to display
*/
defaults: {
radius: 5,
Expand All @@ -89,7 +90,8 @@ Module.register('MMM-Fuel', {
rotateInterval: 60 * 1000, // every minute
updateInterval: 15 * 60 * 1000, // every 15 minutes
provider: 'tankerkoenig',
toFixed: false
toFixed: false,
ids: []
},

/**
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ Gas Station Price Module for MagicMirror<sup>2</sup>
| `rotate` | `true` | Boolean to enable/disable rotation between sort by price and distance. |
| `rotateInterval` | `60000` (1 min) | How fast the sorting should be switched between byPrice and byDistance. |
| `updateInterval` | `900000` (15 mins) | How often should the data be fetched. |
| `ids` | `[]` | Only display the specified Gas Stations. Works only with TankerKoenig. |

### tankerkoenig (Germany only)

Expand Down
128 changes: 100 additions & 28 deletions apis/tankerkoenig.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
* @see https://www.npmjs.com/package/request
*/
const request = require('request');
const Coordinate = require('./utils/Coordinate.js');

/**
* @module apis/tankerkoenig
* @description Queries data from tankerkoenig.de
*
* @requires external:request
* @requires module:Coordinate
*
* @param {Object} config - Configuration.
* @param {number} config.lat - Latitude of Coordinate.
Expand All @@ -31,12 +33,29 @@ const request = require('request');
*/
module.exports = (config) => {
/** @member {string} baseUrl - API url */
const baseUrl = 'https://creativecommons.tankerkoenig.de/json/list.php';
const baseUrl = 'https://creativecommons.tankerkoenig.de/json';

/** @member {Object} options - API url combined with config options. */
const options = {
url: `${baseUrl}?lat=${config.lat}&lng=${config.lng}&rad=${config.radius}&type=all&apikey=${
config.api_key}&sort=dist`
/**
* @function generateOptions
* @description Helper function to generate the options.
*
* @param {string} gasStationId - Optional gas station ID
* @returns {Object.<string>} Options-object
*/
const generateOptions = (gasStationId) => {
let url = baseUrl;

if (config.ids && gasStationId && config.ids.length > 0) {
url += `/detail.php?id=${gasStationId}`;
} else {
url += `/list.php?lat=${config.lat}&lng=${config.lng}&rad=${config.radius}&type=all&sort=dist`;
}

url += `&apikey=${config.api_key}`;

return {
url
};
};

/**
Expand Down Expand Up @@ -95,6 +114,64 @@ module.exports = (config) => {
/* eslint-enable no-param-reassign */
};

/**
* @function requestPrice
* @description Function to fetch the details for a given station.
*
* @param {string} gasStationId - ID of the gas station
*
* @returns {Promise} Data or error message
*/
const requestPrice = gasStationId => new Promise((resolve, reject) => {
request(generateOptions(gasStationId), (error, response, body) => {
if (response.statusCode === 200) {
const parsedBody = JSON.parse(body);

if (parsedBody.ok) {
parsedBody.station.dist = Coordinate.getDistance({
lat: config.lat,
lng: config.lng
}, {
lat: parsedBody.station.lat,
lng: parsedBody.station.lng
});
resolve(parsedBody.station);
} else {
reject(`Error getting station details ${parsedBody.status}`);
}
} else {
reject(`Error getting fuel data ${response.statusCode}`);
}
});
});

/**
* @function parseStationList
* @description Helper function to pars the list of gas stations.
*
* @param {Object[]} stationList - List of gas stations
* @param {getDataCallback} callback - Callback that handles the API data.
*
* @returns {Promise} Data or error message
*/
const parseStationList = (stationList, callback) => {
const stations = stationList.filter(filterStations);

stations.forEach(normalizeStations);

const price = stations.slice(0);
price.sort(sortByPrice);


callback(null, {
types: ['diesel', 'e5', 'e10'],
unit: 'km',
currency: 'EUR',
byPrice: price,
byDistance: stations
});
};

return {
/**
* @callback getDataCallback
Expand All @@ -111,31 +188,26 @@ module.exports = (config) => {
* @param {getDataCallback} callback - Callback that handles the API data.
*/
getData(callback) {
request(options, (error, response, body) => {
if (response.statusCode === 200) {
const parsedBody = JSON.parse(body);
if (parsedBody.ok) {
const stations = parsedBody.stations.filter(filterStations);

stations.forEach(normalizeStations);

const price = stations.slice(0);
price.sort(sortByPrice);

callback(null, {
types: ['diesel', 'e5', 'e10'],
unit: 'km',
currency: 'EUR',
byPrice: price,
byDistance: stations
});
if (config.ids && config.ids.length > 0) {
Promise
.all(config.ids.map(requestPrice))
.then((stationList) => {
parseStationList(stationList, callback);
}, callback);
} else {
request(generateOptions(), (error, response, body) => {
if (response.statusCode === 200) {
const parsedBody = JSON.parse(body);
if (parsedBody.ok) {
parseStationList(parsedBody.stations, callback);
} else {
callback('Error no fuel data');
}
} else {
callback('Error no fuel data');
callback(`Error getting fuel data ${response.statusCode}`);
}
} else {
callback(`Error getting fuel data ${response.statusCode}`);
}
});
});
}
}
};
};
23 changes: 23 additions & 0 deletions apis/utils/Coordinate.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,28 @@ module.exports = {
const λ2 = λ1 + Math.atan2(y, x);

return { lat: rad2deg(φ2), lng: ((rad2deg(λ2) + 540) % 360) - 180 };
},

/**
* @function getDistance
* @description Calculates the distance between two points.
*
* @param {Object.<number, number>} - Start point
* @param {Object.<number, number>} - Target point
* @returns {number} - Distance in kilometers
*/
getDistance(pos1, pos2) {
// Algorithm taken from https://stackoverflow.com/a/27943
/* eslint-disable no-mixed-operators */

const dLat = deg2rad(pos2.lat - pos1.lat);
const dLon = deg2rad(pos2.lng - pos1.lng);

const distance = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(deg2rad(pos1.lat)) * Math.cos(deg2rad(pos2.lat)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(distance), Math.sqrt(1 - distance));

return earth * c / 1000;
}
};