diff --git a/MMM-Fuel.js b/MMM-Fuel.js
index 472d3ce..155c25f 100644
--- a/MMM-Fuel.js
+++ b/MMM-Fuel.js
@@ -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,
@@ -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: []
},
/**
diff --git a/README.md b/README.md
index 535a486..4e88778 100644
--- a/README.md
+++ b/README.md
@@ -60,6 +60,7 @@ Gas Station Price Module for MagicMirror2
| `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)
diff --git a/apis/tankerkoenig.js b/apis/tankerkoenig.js
index d71f2c6..55c35ec 100644
--- a/apis/tankerkoenig.js
+++ b/apis/tankerkoenig.js
@@ -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.
@@ -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.} 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
+ };
};
/**
@@ -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
@@ -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}`);
- }
- });
+ });
+ }
}
};
};
diff --git a/apis/utils/Coordinate.js b/apis/utils/Coordinate.js
index 0a8bc12..a93ee89 100644
--- a/apis/utils/Coordinate.js
+++ b/apis/utils/Coordinate.js
@@ -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.} - Start point
+ * @param {Object.} - 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;
}
};