Skip to content

Commit

Permalink
Merge pull request #98 from fewieden/develop
Browse files Browse the repository at this point in the history
2.4.0
  • Loading branch information
fewieden authored Aug 13, 2022
2 parents 2323336 + 1411d72 commit 5a818da
Show file tree
Hide file tree
Showing 12 changed files with 482 additions and 403 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# MMM-Fuel Changelog

## [2.4.0]

### Added

* [Provider: `gasbuddy`](https://github.com/fewieden/MMM-Fuel/pull/97)
* [Config option: `fade`](https://github.com/fewieden/MMM-Fuel/issues/7)
* [Config option: `showAddressCity`](https://github.com/fewieden/MMM-Fuel/pull/64)

### Changed

* [Migrated provider `nsw` from API v1 to v2 in order to support new region Tasmania (Australia)](https://github.com/fewieden/MMM-Fuel/issues/68#issuecomment-916505199)
* Dependency update

## [2.3.1]

### Fixed
Expand Down
17 changes: 15 additions & 2 deletions MMM-Fuel.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ Module.register('MMM-Fuel', {
* @property {boolean} colored - Flag to render map in colour or greyscale.
* @property {boolean} open - Flag to render column to indicate if the gas stations are open or closed.
* @property {boolean|int} shortenText - Max characters to be shown for name and address.
* @property {boolean} showAddress - Flag to show the gas stations address.
* @property {boolean} showAddress - Flag to show the gas station's address.
* @property {boolean} showAddressCity - Flag to show the gas station's city.
* @property {boolean} showOpenOnly - Flag to show only open gas stations or all.
* @property {boolean} showDistance - Flag to show the distance to your specified position.
* @property {boolean} showBrand - Flag to show the brand instead of the name.
Expand All @@ -61,6 +62,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 {boolean} fade - Fade the list of gas stations.
*/
defaults: {
radius: 5,
Expand All @@ -73,6 +75,7 @@ Module.register('MMM-Fuel', {
open: false,
shortenText: false,
showAddress: true,
showAddressCity: true,
showOpenOnly: false,
showDistance: true,
showBrand: false,
Expand All @@ -85,7 +88,8 @@ Module.register('MMM-Fuel', {
provider: 'tankerkoenig',
toFixed: false,
stationIds: [],
excludeStationIds: []
excludeStationIds: [],
fade: true
},

/**
Expand Down Expand Up @@ -430,5 +434,14 @@ Module.register('MMM-Fuel', {
unit: this.priceList.unit,
maximumFractionDigits: 1
}).format(distance));
this.nunjucksEnvironment().addFilter('fade', (index, total) => {
if (this.config.fade) {
const percentage = (1 - 1 / total * index).toFixed(2);

return `opacity: ${percentage}`;
}

return '';
});
}
});
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,15 @@ Gas Station Price Module for MagicMirror<sup>2</sup>
| `width` | `600` | Width of the map in pixel. |
| `colored` | `false` | Boolean to show the gas stations map colored or not. |
| `shortenText` | `false` | Integer of characters to be shown for name and address. Default shows all. |
| `showAddress` | `true` | Boolean to show the gas stations address. |
| `showAddress` | `true` | Boolean to show the gas station's address. |
| `showOpenOnly` | `false` | Boolean to show only open gas stations or all. |
| `showDistance` | `true` | Boolean to show the distance to your specified position. |
| `showBrand` | `false` | Boolean to show the brand instead of the name. |
| `iconHeader` | `true` | Boolean to display the car icon in the header. |
| `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. **If your value is to small, you risk to get banned from the API provider. I suggest a minimum of 15mins** |
| `fade` | `true` | Boolean to fade out the list of gas stations. |

## Global config

Expand All @@ -85,6 +86,7 @@ or your API access will be suspended.
| `api_key` | REQUIRED | Get an API key for free access to the data of [tankerkoenig.de](https://creativecommons.tankerkoenig.de/#register). |
| `types` | `["diesel"]` | Valid options are `diesel`, `e5` and `e10`. |
| `radius` | `5` | Valid range is 0-25. Set to 0 to disable. Not required if `stationIds` are provided. |
| `showAddressCity` | `true` | Boolean to show the gas station's city. |
| `stationIds` | `[]` | Optional array of fuel station ids to fetch instead of the radius. You can only specify a maximum of 10 and you can find the ids [here](https://creativecommons.tankerkoenig.de/TankstellenFinder/index.html). Using radius and station ids in parallel will result in more API calls. If you run into issues increase the `updateInterval`. |
| `excludeStationIds` | `[]` | Optional array of fuel station ids to exclude from the radius. This is useful e.g. if you got a non public or truck exclusive station in the radius. You can find the ids [here](https://creativecommons.tankerkoenig.de/TankstellenFinder/index.html).|

Expand All @@ -98,6 +100,7 @@ No API key required.
| `types` | `["diesel"]` | Valid options are `diesel`, `e5` and `gas`. |
| `radius` | `5` | Valid range not tested yet. |
| `max` | `5` | The API provider returns maximum of 5 valid datasets. |
| `showAddressCity` | `true` | Boolean to show the gas station's city. |
| `showBrand` | `false` | The API provider does not return brand information. |

### autoblog (USA only)
Expand All @@ -116,7 +119,24 @@ No API key required. The displayed distance is not based on your coordinates but
| `showOpenOnly` | `false` | Not supported |
| `showBrand` | `false` | Not supported |

### nsw (Australia NSW only)
### gasbuddy (USA and Canada only)

No API key required. The displayed distance is not based on your coordinates but on the zip code.

| **Option** | **Default** | **Description** |
| --- | --- | --- |
| `provider` | `"tankerkoenig"` | Make sure you set it to `"gasbuddy"`. |
| `zip` | REQUIRED | The zip code of your address, e.g. `"12345"` |
| `types` | `["regular"]` | Valid options are `regular`, `midgrade`, `premium`, `diesel`, `e85`, and `unl88`. |
| `showDistance` | `false` | Not supported |
| `radius` | `5` | Not supported |
| `lat` | `undefined` | Not supported |
| `lng` | `undefined` | Not supported |
| `open` | `false` | Not supported |
| `showOpenOnly` | `false` | Not supported |
| `showBrand` | `false` | Not supported |

### nsw (Australia NSW and TAS only)

This provider gives no information if the gas stations are open or closed.
Config options should be set accordingly `open`: false and `showOpenOnly`: false.
Expand Down
77 changes: 14 additions & 63 deletions apis/autoblog.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const fetch = require('node-fetch');
*/
const { parse } = require('node-html-parser');

const { fillMissingPrices, sortByDistance, sortByPrice, mergePrices } = require('./utils');

const BASE_URL = 'https://www.autoblog.com';
const MAX_PAGE = 2;

Expand Down Expand Up @@ -59,43 +61,6 @@ function mapGasStation(htmlGasStation, type) {
};
}

/**
* @function fillMissingPrices
* @description Replaces missing price information with max price for type.
*
* @param {Object} station - Gas Station
* @param {Object} maxPricesByType - Maximum price per fuel type.
*
* @returns {void}
*/
function fillMissingPrices(station, maxPricesByType) {
for (const type of config.types) {
if (!station.prices[type]) {
station.prices[type] = `>${maxPricesByType[type]}`;
}
}
}

/**
* @function sortByPrice
* @description Helper function to sort gas stations by price.
*
* @param {Object} a - Gas Station
* @param {Object} b - Gas Station
*
* @returns {number} Sorting weight.
*/
function sortByPrice(a, b) {
const aPrice = a.prices[config.sortBy];
const bPrice = b.prices[config.sortBy];

if (!isNaN(aPrice) || !isNaN(bPrice)) {
return isNaN(aPrice) ? 1 : -1;
}

return 0;
}

/**
* @function fetchPaginatedStations
* @description Paginated API requests for specified type.
Expand Down Expand Up @@ -160,31 +125,17 @@ async function getAllStations() {
}

/**
* @function mergePrices
* @description Merges fuel prices of different types of gas station
* @function getStationKey
* @description Helper to retrieve unique station key.
*
* @param {Object} station - Station
*
* @param {Object[]} responses - List of gas stations with prices of single fuel type.
* @returns {string} Returns unique station key.
*
* @returns {Object} Returns gas stations with merged prices and max prices per fuel type.
* @see apis/README.md
*/
function mergePrices(responses) {
const { indexedStations, maxPricesByType } = responses.reduce(({ indexedStations, maxPricesByType }, station) => {
const stationKey = `${station.name}-${station.address}`;

if (!indexedStations[stationKey]) {
indexedStations[stationKey] = station;
} else {
indexedStations[stationKey].prices[station.fuelType] = station.prices[station.fuelType];
}

if (!maxPricesByType[station.fuelType] || maxPricesByType[station.fuelType] < station.prices[station.fuelType]) {
maxPricesByType[station.fuelType] = station.prices[station.fuelType];
}

return { indexedStations, maxPricesByType };
}, { indexedStations: {}, maxPricesByType: {} });

return { stations: Object.values(indexedStations), maxPricesByType };
function getStationKey(station) {
return `${station.name}-${station.address}`;
}

/**
Expand All @@ -199,14 +150,14 @@ function mergePrices(responses) {
async function getData() {
const responses = await getAllStations();

const { stations, maxPricesByType } = mergePrices(responses);
const { stations, maxPricesByType } = mergePrices(responses, getStationKey);

stations.forEach(station => fillMissingPrices(station, maxPricesByType));
stations.forEach(station => fillMissingPrices(config, station, maxPricesByType));

const filteredStations = stations.filter(station => station.distance <= config.radius);

const stationsSortedByDistance = filteredStations.sort((a, b) => a.distance - b.distance);
const stationsSortedByPrice = [...stationsSortedByDistance].sort(sortByPrice);
const stationsSortedByDistance = filteredStations.sort(sortByDistance);
const stationsSortedByPrice = [...stationsSortedByDistance].sort(sortByPrice.bind(null, config));

return {
types: ['regular', 'premium', 'mid-grade', 'diesel'],
Expand Down
Loading

0 comments on commit 5a818da

Please sign in to comment.