Skip to content

Commit

Permalink
Fix GladysAssistant#726: Replace DarkSky by OpenWeatherMap API integr…
Browse files Browse the repository at this point in the history
…ation (GladysAssistant#837)

* feat(openweather): implementation to API openweather

TODO :
Have a decision about DarkSky (keep it and enable weather with 2 services) or remove it

* feat(openweather): remove darksky integration

* feat(openweather): add unit test

* feat(openweather): solve merge conflicts

* fix: review comment

* Improve integrations tab UI (GladysAssistant#805) -> merge report

* fix: review comments

"si", 'si' -> 'metric'

* Fix weather key in front

Co-authored-by: Julien Mellano <julien.spam82@gmail.com>
  • Loading branch information
Pierre-Gilles and jmellano authored Jul 28, 2020
1 parent ac054ad commit cb47690
Show file tree
Hide file tree
Showing 37 changed files with 812 additions and 2,035 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions front/src/components/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ import SettingsGatewayOpenApi from '../routes/settings/settings-gateway-open-api
// Integrations
import TelegramPage from '../routes/integration/all/telegram';
import CaldavPage from '../routes/integration/all/caldav';
import DarkSkyPage from '../routes/integration/all/darksky';
import OpenWeatherPage from '../routes/integration/all/openweather';
import PhilipsHueSetupPage from '../routes/integration/all/philips-hue/setup-page';
import PhilipsHueDevicePage from '../routes/integration/all/philips-hue/device-page';
import ZwaveNodePage from '../routes/integration/all/zwave/node-page';
Expand Down Expand Up @@ -153,7 +153,7 @@ const AppRouter = connect(

<TelegramPage path="/dashboard/integration/communication/telegram" />
<CaldavPage path="/dashboard/integration/calendar/caldav" />
<DarkSkyPage path="/dashboard/integration/weather/darksky" />
<OpenWeatherPage path="/dashboard/integration/weather/openweather" />
<Redirect
path="/dashboard/integration/device/philips-hue"
to="/dashboard/integration/device/philips-hue/device"
Expand Down
4 changes: 2 additions & 2 deletions front/src/components/boxs/weather/WeatherBox.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const WeatherBox = ({ children, ...props }) => (
<i class="fe fe-bell" />
<span class="pl-2">
<Text id="dashboard.boxes.weather.requestToThirdPartyFailed" />{' '}
<Link href="/dashboard/integration/weather/darksky">
<Link href="/dashboard/integration/weather/openweather">
<Text id="dashboard.boxes.weather.clickHere" />
</Link>
</span>
Expand Down Expand Up @@ -119,7 +119,7 @@ const WeatherBox = ({ children, ...props }) => (
fontSize: '30px'
}}
>
{props.units === 'si' ? 'C' : 'F'}
{props.units === 'metric' ? 'C' : 'F'}
</span>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion front/src/config/demo.json
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@
"humidity": 0.99,
"pressure": 1005.09,
"datetime": "2019-05-09T04:27:57.000Z",
"units": "si",
"units": "metric",
"wind_speed": 1.96,
"weather": "rain",
"house": {
Expand Down
16 changes: 8 additions & 8 deletions front/src/config/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@
"weather": {
"editHouseLabel": "Select a house. I will use its latitude/longitude to get the weather.",
"houseHasNoCoordinates": "Your house has no coordinates defined. Go to Gladys parameters to define the position of your house.",
"serviceNotConfigured": "The DarkSky service is not configured. Please go to the 'Integrations' tab, and configure the DarkSky service.",
"requestToThirdPartyFailed": "The request to DarkSKy API failed. Is your Gladys instance connected to the internet? Please go to the DarkSky configuration panel to troubleshoot this problem.",
"clickHere": "Click here to access the DarkSky configuration panel.",
"serviceNotConfigured": "The OpenWeather service is not configured. Please go to the 'Integrations' tab, and configure the OpenWeather service.",
"requestToThirdPartyFailed": "The request to OpenWeather API failed. Is your Gladys instance connected to the internet? Please go to the OpenWeather configuration panel to troubleshoot this problem.",
"clickHere": "Click here to access the OpenWeather configuration panel.",
"unknownError": "We are unable to get the weather for this house. Did you define a house for this box?"
},
"devicesInRoom": {
Expand Down Expand Up @@ -398,13 +398,13 @@
"nodeAddedDescription": "Wait a few seconds while we get all of the information from this node..."
}
},
"darkSky": {
"title": "DarkSky",
"openWeather": {
"title": "OpenWeather API",
"description": "Get the weather in Gladys.",
"introduction": "This integration helps you integrate with the DarkSky API to get the weather in Gladys.",
"instructions": "You first need to create an account on the DarkSky API website: <a href=\"https://darksky.net/dev\">https://darksky.net/dev</a>.",
"introduction": "This integration helps you integrate with OpenWeather API to get the weather in Gladys.",
"instructions": "You first need to create an account on OpenWeather API website: <a href=\"https://openweathermap.org/api\">https://openweathermap.org/api</a>.",
"apiKeyLabel": "Then, enter your API key here:",
"apiKeyPlaceholder": "Enter DarkSky API key",
"apiKeyPlaceholder": "Enter OpenWeather API key",
"saveButton": "Save",
"instructionsToUse": "To use this integration, go to the dashboard and create a weather box."
},
Expand Down
16 changes: 8 additions & 8 deletions front/src/config/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@
"weather": {
"editHouseLabel": "Sélectionnez une maison. J'utiliserais les latitude/longitude pour obtenir la météo.",
"houseHasNoCoordinates": "Les coordonnées de votre maison ne sont pas définies. Accédez aux paramètres Gladys pour définir la position de votre maison.",
"serviceNotConfigured": "Le service DarkSky n'est pas configuré. Veuillez accéder à l'onglet «Intégrations» et configurer le service DarkSky.",
"requestToThirdPartyFailed": "La requête à l'API DarkSKy a échouée. Votre instance Gladys est-elle connectée à Internet? Veuillez vous rendre dans le panneau de configuration de DarkSky pour résoudre ce problème.",
"clickHere": "Cliquez ici pour accéder au panneau de configuration de DarkSky.",
"serviceNotConfigured": "Le service OpenWeather n'est pas configuré. Veuillez accéder à l'onglet «Intégrations» et configurer le service OpenWeather.",
"requestToThirdPartyFailed": "La requête à l'API OpenWeather a échouée. Votre instance Gladys est-elle connectée à Internet? Veuillez vous rendre dans le panneau de configuration de OpenWeather pour résoudre ce problème.",
"clickHere": "Cliquez ici pour accéder au panneau de configuration de OpenWeather.",
"unknownError": "Nous ne pouvons pas obtenir la météo pour cette maison. Avez-vous défini une maison pour cette box ?"
},
"devicesInRoom": {
Expand Down Expand Up @@ -442,13 +442,13 @@
"nodeAddedDescription": "Attendez quelques secondes pendant que nous obtenons toutes les informations de ce nœud..."
}
},
"darkSky": {
"title": "DarkSky",
"openWeather": {
"title": "API OpenWeather",
"description": "Récupérer la météo dans Gladys.",
"introduction": "Cette intégration vous aide à intégrer l'API DarkSky pour obtenir la météo dans Gladys.",
"instructions": "Vous devez d'abord créer un compte sur le site Web de l'API DarkSky : <a href=\"https://darksky.net/dev\">https://darksky.net/dev</a>.",
"introduction": "Cette intégration vous aide à intégrer l'API OpenWeather pour obtenir la météo dans Gladys.",
"instructions": "Vous devez d'abord créer un compte sur le site Web de l'API d'OpenWeather : <a href=\"https://openweathermap.org/api\">https://openweathermap.org/api</a>.",
"apiKeyLabel": "Saisissez ensuite votre clé API ici :",
"apiKeyPlaceholder": "Entrer la clé API DarkSky",
"apiKeyPlaceholder": "Entrer la clé API OpenWeather",
"saveButton": "Sauvegarder",
"instructionsToUse": "Pour utiliser cette intégration, accédez au tableau de bord et créez une box météo."
},
Expand Down
4 changes: 2 additions & 2 deletions front/src/config/integrations/weathers.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[
{
"key": "darkSky",
"img": "/assets/integrations/cover/darksky.jpg"
"key": "openWeather",
"img": "/assets/integrations/cover/openweather.jpg"
}
]
51 changes: 0 additions & 51 deletions front/src/routes/integration/all/darksky/actions.js

This file was deleted.

20 changes: 0 additions & 20 deletions front/src/routes/integration/all/darksky/index.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Text, MarkupText, Localizer } from 'preact-i18n';
import cx from 'classnames';

const DarkSkyPage = ({ children, ...props }) => (
const OpenWeatherPage = ({ children, ...props }) => (
<div class="page">
<div class="page-main">
<div class="my-3 my-md-5">
Expand All @@ -18,27 +18,27 @@ const DarkSkyPage = ({ children, ...props }) => (
<div class="loader" />
<div class="dimmer-content">
<h2>
<Text id="integration.darkSky.title" />
<Text id="integration.openWeather.title" />
</h2>
<p>
<Text id="integration.darkSky.introduction" />
<Text id="integration.openWeather.introduction" />
</p>
<p>
<MarkupText id="integration.darkSky.instructions" />
<MarkupText id="integration.openWeather.instructions" />
</p>
<form onSubmit={props.saveApiKey}>
<div class="form-group">
<div class="form-label">
<Text id="integration.darkSky.apiKeyLabel" />
<Text id="integration.openWeather.apiKeyLabel" />
</div>
<div class="input-group">
<Localizer>
<input
type="text"
class="form-control"
placeholder={<Text id="integration.darkSky.apiKeyPlaceholder" />}
placeholder={<Text id="integration.openWeather.apiKeyPlaceholder" />}
onInput={props.updateApiKey}
value={props.darkSkyApiKey}
value={props.openWeatherApiKey}
/>
</Localizer>
<span class="input-group-append">
Expand All @@ -48,15 +48,15 @@ const DarkSkyPage = ({ children, ...props }) => (
})}
type="submit"
>
<Text id="integration.darkSky.saveButton" />
<Text id="integration.openWeather.saveButton" />
</button>
</span>
</div>
</div>

<div class="form-group">
<label>
<Text id="integration.darkSky.instructionsToUse" />
<Text id="integration.openWeather.instructionsToUse" />
</label>
</div>
</form>
Expand All @@ -72,4 +72,4 @@ const DarkSkyPage = ({ children, ...props }) => (
</div>
);

export default DarkSkyPage;
export default OpenWeatherPage;
51 changes: 51 additions & 0 deletions front/src/routes/integration/all/openweather/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { RequestStatus } from '../../../../utils/consts';

const actions = store => ({
updateApiKey(state, e) {
store.setState({
openWeatherApiKey: e.target.value
});
},
async getApiKey(state) {
store.setState({
openWeatherGetApiKeyStatus: RequestStatus.Getting
});
try {
const variable = await state.httpClient.get('/api/v1/service/openweather/variable/OPENWEATHER_API_KEY');
store.setState({
openWeatherApiKey: variable.value,
openWeatherGetApiKeyStatus: RequestStatus.Success
});
} catch (e) {
store.setState({
openWeatherGetApiKeyStatus: RequestStatus.Error
});
}
},
async saveApiKey(state, e) {
e.preventDefault();
store.setState({
openWeatherSaveApiKeyStatus: RequestStatus.Getting
});
try {
store.setState({
openWeatheryApiKey: state.openWeatherApiKey.trim()
});
// save api key
await state.httpClient.post('/api/v1/service/openweather/variable/OPENWEATHER_API_KEY', {
value: state.openWeatherApiKey.trim()
});
// start service
await state.httpClient.post('/api/v1/service/openweather/start');
store.setState({
openWeatherSaveApiKeyStatus: RequestStatus.Success
});
} catch (e) {
store.setState({
openWeatherSaveApiKeyStatus: RequestStatus.Error
});
}
}
});

export default actions;
21 changes: 21 additions & 0 deletions front/src/routes/integration/all/openweather/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Component } from 'preact';
import { connect } from 'unistore/preact';
import actions from './actions';
import OpenWeatherPage from './OpenWeather';
import { RequestStatus } from '../../../../utils/consts';

@connect('user,openWeatherApiKey,openWeatherSaveApiKeyStatus,openWeatherGetApiKeyStatus', actions)
class OpenWeatherIntegration extends Component {
componentWillMount() {
this.props.getApiKey();
}

render(props, {}) {
const loading =
props.openWeatherSaveApiKeyStatus === RequestStatus.Getting ||
props.openWeatherGetApiKeyStatus === RequestStatus.Getting;
return <OpenWeatherPage {...props} loading={loading} />;
}
}

export default OpenWeatherIntegration;
4 changes: 2 additions & 2 deletions server/api/controllers/weather.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module.exports = function WeatherController(gladys) {
* "humidity": 0.58,
* "pressure": 1005.98,
* "datetime": "2019-05-09T04:26:42.000Z",
* "units": "si",
* "units": "metric",
* "wind_speed": 5.06,
* "weather": "cloud"
* }
Expand All @@ -39,7 +39,7 @@ module.exports = function WeatherController(gladys) {
* "humidity": 0.58,
* "pressure": 1005.98,
* "datetime": "2019-05-09T04:26:42.000Z",
* "units": "si",
* "units": "metric",
* "wind_speed": 5.06,
* "weather": "cloud"
* }
Expand Down
2 changes: 1 addition & 1 deletion server/config/brain/weather/answers.en.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
},
{
"label": "weather.get.fail.not-configured",
"answers": ["You need to configure DarkSky API in the Integration tab before using this feature."]
"answers": ["You need to configure OpenWeather API in the Integration tab before using this feature."]
},
{
"label": "weather.get.fail.no-house",
Expand Down
2 changes: 1 addition & 1 deletion server/lib/weather/weather.command.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ async function command(message, classification, context) {
case 'weather.get':
weather = await this.get(house);
context.temperature = weather.temperature;
context.units = weather.units === 'si' ? '°C' : '°F';
context.units = weather.units === 'metric' ? '°C' : '°F';
await this.messageManager.replyByIntent(message, `weather.get.success.${weather.weather}`, context);
break;
default:
Expand Down
10 changes: 5 additions & 5 deletions server/lib/weather/weather.get.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ const { ServiceNotConfiguredError } = require('../../utils/coreErrors');
* longitude: -2,
* offset: 0,
* language: 'fr',
* units: 'si'
* units: 'metric'
* });
*/
function get(options) {
const darkSkyService = this.service.getService('darksky');
if (darkSkyService === null) {
throw new ServiceNotConfiguredError(`Service darksky is not found or not configured.`);
const openweatherService = this.service.getService('openweather');
if (openweatherService === null) {
throw new ServiceNotConfiguredError(`Service openweather is not found or not configured.`);
}
return darkSkyService.weather.get(options);
return openweatherService.weather.get(options);
}

module.exports = {
Expand Down
Loading

0 comments on commit cb47690

Please sign in to comment.