diff --git a/homeassistant/components/weather/ipma.py b/homeassistant/components/weather/ipma.py
new file mode 100644
index 0000000000000000000000000000000000000000..ef4f1b349d72a5c3d87d3d0a81fdb45cf04f3992
--- /dev/null
+++ b/homeassistant/components/weather/ipma.py
@@ -0,0 +1,172 @@
+"""
+Support for IPMA weather service.
+
+For more details about this platform, please refer to the documentation at
+https://home-assistant.io/components/weather.ipma/
+"""
+import logging
+from datetime import timedelta
+
+import async_timeout
+import voluptuous as vol
+
+from homeassistant.components.weather import (
+    WeatherEntity, PLATFORM_SCHEMA, ATTR_FORECAST_CONDITION,
+    ATTR_FORECAST_PRECIPITATION, ATTR_FORECAST_TEMP,
+    ATTR_FORECAST_TEMP_LOW, ATTR_FORECAST_TIME)
+from homeassistant.const import \
+    CONF_NAME, TEMP_CELSIUS, CONF_LATITUDE, CONF_LONGITUDE
+from homeassistant.helpers.aiohttp_client import async_get_clientsession
+from homeassistant.helpers import config_validation as cv
+from homeassistant.util import Throttle
+
+REQUIREMENTS = ['pyipma==1.1.3']
+
+_LOGGER = logging.getLogger(__name__)
+
+ATTRIBUTION = 'Instituto Português do Mar e Atmosfera'
+
+ATTR_WEATHER_DESCRIPTION = "description"
+
+MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=30)
+
+CONDITION_CLASSES = {
+    'cloudy': [4, 5, 24, 25, 27],
+    'fog': [16, 17, 26],
+    'hail': [21, 22],
+    'lightning': [19],
+    'lightning-rainy': [20, 23],
+    'partlycloudy': [2, 3],
+    'pouring': [8, 11],
+    'rainy': [6, 7, 9, 10, 12, 13, 14, 15],
+    'snowy': [18],
+    'snowy-rainy': [],
+    'sunny': [1],
+    'windy': [],
+    'windy-variant': [],
+    'exceptional': [],
+}
+
+PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
+    vol.Optional(CONF_NAME): cv.string,
+    vol.Optional(CONF_LATITUDE): cv.latitude,
+    vol.Optional(CONF_LONGITUDE): cv.longitude,
+})
+
+
+async def async_setup_platform(hass, config, async_add_devices,
+                               discovery_info=None):
+    """Set up the ipma platform."""
+    latitude = config.get(CONF_LATITUDE, hass.config.latitude)
+    longitude = config.get(CONF_LONGITUDE, hass.config.longitude)
+
+    if None in (latitude, longitude):
+        _LOGGER.error("Latitude or longitude not set in Home Assistant config")
+        return
+
+    from pyipma import Station
+
+    websession = async_get_clientsession(hass)
+    with async_timeout.timeout(10, loop=hass.loop):
+        station = await Station.get(websession, float(latitude),
+                                    float(longitude))
+
+    _LOGGER.debug("Initializing ipma weather: coordinates %s, %s",
+                  latitude, longitude)
+
+    async_add_devices([IPMAWeather(station, config)], True)
+
+
+class IPMAWeather(WeatherEntity):
+    """Representation of a weather condition."""
+
+    def __init__(self, station, config):
+        """Initialise the platform with a data instance and station name."""
+        self._station_name = config.get(CONF_NAME, station.local)
+        self._station = station
+        self._condition = None
+        self._forecast = None
+        self._description = None
+
+    @Throttle(MIN_TIME_BETWEEN_UPDATES)
+    async def async_update(self):
+        """Update Condition and Forecast."""
+        with async_timeout.timeout(10, loop=self.hass.loop):
+            self._condition = await self._station.observation()
+            self._forecast = await self._station.forecast()
+            self._description = self._forecast[0].description
+
+    @property
+    def attribution(self):
+        """Return the attribution."""
+        return ATTRIBUTION
+
+    @property
+    def name(self):
+        """Return the name of the station."""
+        return self._station_name
+
+    @property
+    def condition(self):
+        """Return the current condition."""
+        return next((k for k, v in CONDITION_CLASSES.items()
+                     if self._forecast[0].idWeatherType in v), None)
+
+    @property
+    def temperature(self):
+        """Return the current temperature."""
+        return self._condition.temperature
+
+    @property
+    def pressure(self):
+        """Return the current pressure."""
+        return self._condition.pressure
+
+    @property
+    def humidity(self):
+        """Return the name of the sensor."""
+        return self._condition.humidity
+
+    @property
+    def wind_speed(self):
+        """Return the current windspeed."""
+        return self._condition.windspeed
+
+    @property
+    def wind_bearing(self):
+        """Return the current wind bearing (degrees)."""
+        return self._condition.winddirection
+
+    @property
+    def temperature_unit(self):
+        """Return the unit of measurement."""
+        return TEMP_CELSIUS
+
+    @property
+    def forecast(self):
+        """Return the forecast array."""
+        if self._forecast:
+            fcdata_out = []
+            for data_in in self._forecast:
+                data_out = {}
+                data_out[ATTR_FORECAST_TIME] = data_in.forecastDate
+                data_out[ATTR_FORECAST_CONDITION] =\
+                    next((k for k, v in CONDITION_CLASSES.items()
+                          if int(data_in.idWeatherType) in v), None)
+                data_out[ATTR_FORECAST_TEMP_LOW] = data_in.tMin
+                data_out[ATTR_FORECAST_TEMP] = data_in.tMax
+                data_out[ATTR_FORECAST_PRECIPITATION] = data_in.precipitaProb
+
+                fcdata_out.append(data_out)
+
+            return fcdata_out
+
+    @property
+    def device_state_attributes(self):
+        """Return the state attributes."""
+        data = dict()
+
+        if self._description:
+            data[ATTR_WEATHER_DESCRIPTION] = self._description
+
+        return data
diff --git a/requirements_all.txt b/requirements_all.txt
index fd2bb5b4f5a1e54cbfe7f833fa39c50dd1805d97..fcd1e3726e94056344988816f481544b16f8bbf1 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -834,6 +834,9 @@ pyialarm==0.2
 # homeassistant.components.device_tracker.icloud
 pyicloud==0.9.1
 
+# homeassistant.components.weather.ipma
+pyipma==1.1.3
+
 # homeassistant.components.sensor.irish_rail_transport
 pyirishrail==0.0.2
 
diff --git a/tests/components/weather/test_ipma.py b/tests/components/weather/test_ipma.py
new file mode 100644
index 0000000000000000000000000000000000000000..7df6166a2b6a18a73386ffcaaf9783f500c0be85
--- /dev/null
+++ b/tests/components/weather/test_ipma.py
@@ -0,0 +1,85 @@
+"""The tests for the IPMA weather component."""
+import unittest
+from unittest.mock import patch
+from collections import namedtuple
+
+from homeassistant.components import weather
+from homeassistant.components.weather import (
+    ATTR_WEATHER_HUMIDITY, ATTR_WEATHER_PRESSURE, ATTR_WEATHER_TEMPERATURE,
+    ATTR_WEATHER_WIND_BEARING, ATTR_WEATHER_WIND_SPEED)
+from homeassistant.util.unit_system import METRIC_SYSTEM
+from homeassistant.setup import setup_component
+
+from tests.common import get_test_home_assistant, MockDependency
+
+
+class MockStation():
+    """Mock Station from pyipma."""
+
+    @classmethod
+    async def get(cls, websession, lat, lon):
+        """Mock Factory."""
+        return MockStation()
+
+    async def observation(self):
+        """Mock Observation."""
+        Observation = namedtuple('Observation', ['temperature', 'humidity',
+                                                 'windspeed', 'winddirection',
+                                                 'precipitation', 'pressure',
+                                                 'description'])
+
+        return Observation(18, 71.0, 3.94, 'NW', 0, 1000.0, '---')
+
+    async def forecast(self):
+        """Mock Forecast."""
+        Forecast = namedtuple('Forecast', ['precipitaProb', 'tMin', 'tMax',
+                                           'predWindDir', 'idWeatherType',
+                                           'classWindSpeed', 'longitude',
+                                           'forecastDate', 'classPrecInt',
+                                           'latitude', 'description'])
+
+        return [Forecast(73.0, 13.7, 18.7, 'NW', 6, 2, -8.64,
+                         '2018-05-31', 2, 40.61,
+                         'Aguaceiros, com vento Moderado de Noroeste')]
+
+    @property
+    def local(self):
+        """Mock location."""
+        return "HomeTown"
+
+
+class TestIPMA(unittest.TestCase):
+    """Test the IPMA weather component."""
+
+    def setUp(self):
+        """Setup things to be run when tests are started."""
+        self.hass = get_test_home_assistant()
+        self.hass.config.units = METRIC_SYSTEM
+        self.lat = self.hass.config.latitude = 40.00
+        self.lon = self.hass.config.longitude = -8.00
+
+    def tearDown(self):
+        """Stop down everything that was started."""
+        self.hass.stop()
+
+    @MockDependency("pyipma")
+    @patch("pyipma.Station", new=MockStation)
+    def test_setup(self, mock_pyipma):
+        """Test for successfully setting up the IPMA platform."""
+        self.assertTrue(setup_component(self.hass, weather.DOMAIN, {
+            'weather': {
+                'name': 'HomeTown',
+                'platform': 'ipma',
+            }
+        }))
+
+        state = self.hass.states.get('weather.hometown')
+        self.assertEqual(state.state, 'rainy')
+
+        data = state.attributes
+        self.assertEqual(data.get(ATTR_WEATHER_TEMPERATURE), 18.0)
+        self.assertEqual(data.get(ATTR_WEATHER_HUMIDITY), 71)
+        self.assertEqual(data.get(ATTR_WEATHER_PRESSURE), 1000.0)
+        self.assertEqual(data.get(ATTR_WEATHER_WIND_SPEED), 3.94)
+        self.assertEqual(data.get(ATTR_WEATHER_WIND_BEARING), 'NW')
+        self.assertEqual(state.attributes.get('friendly_name'), 'HomeTown')