diff --git a/homeassistant/components/climate/melissa.py b/homeassistant/components/climate/melissa.py
new file mode 100644
index 0000000000000000000000000000000000000000..1e4ceac0edf396c0e80c7923a71817c8da0aa400
--- /dev/null
+++ b/homeassistant/components/climate/melissa.py
@@ -0,0 +1,274 @@
+"""
+Support for Melissa Climate A/C.
+
+For more details about this platform, please refer to the documentation
+https://home-assistant.io/components/climate.melissa/
+"""
+import logging
+
+from homeassistant.components.climate import ClimateDevice, \
+    SUPPORT_OPERATION_MODE, SUPPORT_TARGET_TEMPERATURE, SUPPORT_ON_OFF, \
+    STATE_AUTO, STATE_HEAT, STATE_COOL, STATE_DRY, STATE_FAN_ONLY, \
+    SUPPORT_FAN_MODE
+from homeassistant.components.fan import SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH
+from homeassistant.components.melissa import DATA_MELISSA, DOMAIN
+from homeassistant.const import TEMP_CELSIUS, STATE_ON, STATE_OFF, \
+    STATE_UNKNOWN, STATE_IDLE, ATTR_TEMPERATURE, PRECISION_WHOLE
+
+DEPENDENCIES = [DOMAIN]
+
+_LOGGER = logging.getLogger(__name__)
+
+SUPPORT_FLAGS = (SUPPORT_TARGET_TEMPERATURE | SUPPORT_OPERATION_MODE |
+                 SUPPORT_ON_OFF | SUPPORT_FAN_MODE)
+
+
+def setup_platform(hass, config, add_devices, discovery_info=None):
+    """Iterate through and add all Melissa devices."""
+    api = hass.data[DATA_MELISSA]
+    devices = api.fetch_devices().values()
+
+    all_devices = []
+
+    for device in devices:
+        all_devices.append(MelissaClimate(
+            api, device['serial_number'], device))
+
+    add_devices(all_devices)
+
+
+class MelissaClimate(ClimateDevice):
+    """Representation of a Melissa Climate device."""
+
+    def __init__(self, api, serial_number, init_data):
+        """Initialize the climate device."""
+        self._name = init_data['name']
+        self._api = api
+        self._serial_number = serial_number
+        self._data = init_data['controller_log']
+        self._state = None
+        self._cur_settings = None
+
+    @property
+    def name(self):
+        """Return the name of the thermostat, if any."""
+        return self._name
+
+    @property
+    def is_on(self):
+        """Return current state."""
+        if self._cur_settings is not None:
+            return self._cur_settings[self._api.STATE] in (
+                self._api.STATE_ON, self._api.STATE_IDLE)
+        else:
+            _LOGGER.info("Can't determine state of %s", self.entity_id)
+            return STATE_UNKNOWN
+
+    @property
+    def current_fan_mode(self):
+        """Return the current fan mode."""
+        if self._cur_settings is not None:
+            return self.melissa_fan_to_hass(
+                self._cur_settings[self._api.FAN])
+        else:
+            _LOGGER.info(
+                "Can't determine current fan mode for %s", self.entity_id)
+            return STATE_UNKNOWN
+
+    @property
+    def current_temperature(self):
+        """Return the current temperature."""
+        if self._data:
+            return self._data[self._api.TEMP]
+        else:
+            _LOGGER.info(
+                "Can't determine current temperature for %s", self.entity_id)
+            return None
+
+    @property
+    def target_temperature_step(self):
+        """Return the supported step of target temperature."""
+        return PRECISION_WHOLE
+
+    @property
+    def current_operation(self):
+        """Return the current operation mode."""
+        if self._cur_settings is not None:
+            return self.melissa_op_to_hass(
+                self._cur_settings[self._api.MODE])
+        else:
+            _LOGGER.info(
+                "Can't determine current operation mode of %s", self.entity_id)
+            return STATE_UNKNOWN
+
+    @property
+    def operation_list(self):
+        """Return the list of available operation modes."""
+        return [
+            STATE_AUTO, STATE_HEAT, STATE_COOL, STATE_DRY, STATE_FAN_ONLY
+        ]
+
+    @property
+    def fan_list(self):
+        """List of available fan modes."""
+        return [
+            STATE_AUTO, SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH
+        ]
+
+    @property
+    def target_temperature(self):
+        """Return the temperature we try to reach."""
+        if self._cur_settings is not None:
+            return self._cur_settings[self._api.TEMP]
+        else:
+            _LOGGER.info(
+                "Can not determine current target temperature for %s",
+                self.entity_id)
+            return STATE_UNKNOWN
+
+    @property
+    def state(self):
+        """Return current state."""
+        if self._cur_settings is not None:
+            return self.melissa_state_to_hass(
+                self._cur_settings[self._api.STATE])
+        else:
+            _LOGGER.info("Cant determine current state for %s", self.entity_id)
+            return STATE_UNKNOWN
+
+    @property
+    def temperature_unit(self):
+        """Return the unit of measurement which this thermostat uses."""
+        return TEMP_CELSIUS
+
+    @property
+    def min_temp(self):
+        """Return the minimum supported temperature for the thermostat."""
+        return 16
+
+    @property
+    def max_temp(self):
+        """Return the maximum supported temperature for the thermostat."""
+        return 30
+
+    @property
+    def supported_features(self):
+        """Return the list of supported features."""
+        return SUPPORT_FLAGS
+
+    def set_temperature(self, **kwargs):
+        """Set new target temperature."""
+        temp = kwargs.get(ATTR_TEMPERATURE)
+        return self.send({self._api.TEMP: temp})
+
+    def set_fan_mode(self, fan):
+        """Set fan mode."""
+        fan_mode = self.hass_fan_to_melissa(fan)
+        return self.send({self._api.FAN: fan_mode})
+
+    def set_operation_mode(self, operation_mode):
+        """Set operation mode."""
+        mode = self.hass_mode_to_melissa(operation_mode)
+        return self.send({self._api.MODE: mode})
+
+    def turn_on(self):
+        """Turn on device."""
+        return self.send({self._api.STATE: self._api.STATE_ON})
+
+    def turn_off(self):
+        """Turn off device."""
+        return self.send({self._api.STATE: self._api.STATE_OFF})
+
+    def send(self, value):
+        """Sending action to service."""
+        try:
+            old_value = self._cur_settings.copy()
+            self._cur_settings.update(value)
+        except AttributeError:
+            old_value = None
+        if not self._api.send(self._serial_number, self._cur_settings):
+            self._cur_settings = old_value
+            return False
+        else:
+            return True
+
+    def update(self):
+        """Get latest data from Melissa."""
+        try:
+            self._data = self._api.status(cached=True)[self._serial_number]
+            self._cur_settings = self._api.cur_settings(
+                self._serial_number
+            )['controller']['_relation']['command_log']
+        except KeyError:
+            _LOGGER.warning(
+                'Unable to update component %s', self.entity_id)
+
+    def melissa_state_to_hass(self, state):
+        """Translate Melissa states to hass states."""
+        if state == self._api.STATE_ON:
+            return STATE_ON
+        elif state == self._api.STATE_OFF:
+            return STATE_OFF
+        elif state == self._api.STATE_IDLE:
+            return STATE_IDLE
+        else:
+            return STATE_UNKNOWN
+
+    def melissa_op_to_hass(self, mode):
+        """Translate Melissa modes to hass states."""
+        if mode == self._api.MODE_AUTO:
+            return STATE_AUTO
+        elif mode == self._api.MODE_HEAT:
+            return STATE_HEAT
+        elif mode == self._api.MODE_COOL:
+            return STATE_COOL
+        elif mode == self._api.MODE_DRY:
+            return STATE_DRY
+        elif mode == self._api.MODE_FAN:
+            return STATE_FAN_ONLY
+        else:
+            _LOGGER.warning(
+                "Operation mode %s could not be mapped to hass", mode)
+            return STATE_UNKNOWN
+
+    def melissa_fan_to_hass(self, fan):
+        """Translate Melissa fan modes to hass modes."""
+        if fan == self._api.FAN_AUTO:
+            return STATE_AUTO
+        elif fan == self._api.FAN_LOW:
+            return SPEED_LOW
+        elif fan == self._api.FAN_MEDIUM:
+            return SPEED_MEDIUM
+        elif fan == self._api.FAN_HIGH:
+            return SPEED_HIGH
+        else:
+            _LOGGER.warning("Fan mode %s could not be mapped to hass", fan)
+            return STATE_UNKNOWN
+
+    def hass_mode_to_melissa(self, mode):
+        """Translate hass states to melissa modes."""
+        if mode == STATE_AUTO:
+            return self._api.MODE_AUTO
+        elif mode == STATE_HEAT:
+            return self._api.MODE_HEAT
+        elif mode == STATE_COOL:
+            return self._api.MODE_COOL
+        elif mode == STATE_DRY:
+            return self._api.MODE_DRY
+        elif mode == STATE_FAN_ONLY:
+            return self._api.MODE_FAN
+        else:
+            _LOGGER.warning("Melissa have no setting for %s mode", mode)
+
+    def hass_fan_to_melissa(self, fan):
+        """Translate hass fan modes to melissa modes."""
+        if fan == STATE_AUTO:
+            return self._api.FAN_AUTO
+        elif fan == SPEED_LOW:
+            return self._api.FAN_LOW
+        elif fan == SPEED_MEDIUM:
+            return self._api.FAN_MEDIUM
+        elif fan == SPEED_HIGH:
+            return self._api.FAN_HIGH
+        else:
+            _LOGGER.warning("Melissa have no setting for %s fan mode", fan)
diff --git a/homeassistant/components/melissa.py b/homeassistant/components/melissa.py
new file mode 100644
index 0000000000000000000000000000000000000000..ae82b96222ea5dfea8488783ed82368cc6d0c640
--- /dev/null
+++ b/homeassistant/components/melissa.py
@@ -0,0 +1,44 @@
+"""
+Support for Melissa climate.
+
+For more details about this platform, please refer to the documentation at
+https://home-assistant.io/components/melissa/
+"""
+import logging
+
+import voluptuous as vol
+
+from homeassistant.const import CONF_USERNAME, CONF_PASSWORD
+from homeassistant.helpers import config_validation as cv
+from homeassistant.helpers.discovery import load_platform
+
+REQUIREMENTS = ["py-melissa-climate==1.0.1"]
+
+_LOGGER = logging.getLogger(__name__)
+
+DOMAIN = "melissa"
+DATA_MELISSA = 'MELISSA'
+
+
+CONFIG_SCHEMA = vol.Schema({
+    DOMAIN: vol.Schema({
+        vol.Required(CONF_USERNAME): cv.string,
+        vol.Required(CONF_PASSWORD): cv.string,
+    }),
+}, extra=vol.ALLOW_EXTRA)
+
+
+def setup(hass, config):
+    """Set up the Melissa Climate component."""
+    import melissa
+
+    conf = config[DOMAIN]
+    username = conf.get(CONF_USERNAME)
+    password = conf.get(CONF_PASSWORD)
+
+    api = melissa.Melissa(username=username, password=password)
+    hass.data[DATA_MELISSA] = api
+
+    load_platform(hass, 'sensor', DOMAIN, {})
+    load_platform(hass, 'climate', DOMAIN, {})
+    return True
diff --git a/homeassistant/components/sensor/melissa.py b/homeassistant/components/sensor/melissa.py
new file mode 100644
index 0000000000000000000000000000000000000000..97645cb9dd4f1398f0f4cf8813433ff487bf2de1
--- /dev/null
+++ b/homeassistant/components/sensor/melissa.py
@@ -0,0 +1,98 @@
+"""
+Support for Melissa climate Sensors.
+
+For more details about this platform, please refer to the documentation at
+https://home-assistant.io/components/sensor.melissa/
+"""
+import logging
+
+from homeassistant.components.melissa import DOMAIN, DATA_MELISSA
+from homeassistant.const import TEMP_CELSIUS, STATE_UNKNOWN
+from homeassistant.helpers.entity import Entity
+
+DEPENDENCIES = [DOMAIN]
+
+_LOGGER = logging.getLogger(__name__)
+
+
+def setup_platform(hass, config, add_devices, discovery_info=None):
+    """Setup the melissa sensor platform."""
+    sensors = []
+    api = hass.data[DATA_MELISSA]
+    devices = api.fetch_devices().values()
+
+    for device in devices:
+        sensors.append(MelissaTemperatureSensor(device, api))
+        sensors.append(MelissaHumiditySensor(device, api))
+    add_devices(sensors)
+
+
+class MelissaSensor(Entity):
+    """Representation of a Melissa Sensor."""
+
+    _type = 'generic'
+
+    def __init__(self, device, api):
+        """Initialize the sensor."""
+        self._api = api
+        self._state = STATE_UNKNOWN
+        self._name = '{0} {1}'.format(
+            device['name'],
+            self._type
+        )
+        self._serial = device['serial_number']
+        self._data = device['controller_log']
+
+    @property
+    def name(self):
+        """Return the name of the sensor."""
+        return self._name
+
+    @property
+    def state(self):
+        """Return the state of the sensor."""
+        return self._state
+
+    def update(self):
+        """Fetch status from melissa."""
+        self._data = self._api.status(cached=True)
+
+
+class MelissaTemperatureSensor(MelissaSensor):
+    """Representation of a Melissa temperature Sensor."""
+
+    _type = 'temperature'
+    _unit = TEMP_CELSIUS
+
+    @property
+    def unit_of_measurement(self):
+        """Return the unit of measurement."""
+        return self._unit
+
+    def update(self):
+        """Fetch new state data for the sensor."""
+        super().update()
+        try:
+            self._state = self._data[self._serial]['temp']
+        except KeyError:
+            _LOGGER.warning("Unable to get temperature for %s", self.entity_id)
+
+
+class MelissaHumiditySensor(MelissaSensor):
+    """Representation of a Melissa humidity Sensor."""
+
+    _type = 'humidity'
+    _unit = '%'
+
+    @property
+    def unit_of_measurement(self):
+        """Return the unit of measurement."""
+        return self._unit
+
+    def update(self):
+        """Fetch new state data for the sensor."""
+        super().update()
+        try:
+            self._state = self._data[self._serial]['humidity']
+        except KeyError:
+            _LOGGER.warning("Unable to get humidity for %s", self.entity_id)
diff --git a/requirements_all.txt b/requirements_all.txt
index 20dc82cb95a6f717a1f008cd9ec49b50c2e776d4..3bf11f9e27c12f3d61cd9e3dda71f17ecfa20e27 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -623,6 +623,9 @@ py-canary==0.2.3
 # homeassistant.components.sensor.cpuspeed
 py-cpuinfo==3.3.0
 
+# homeassistant.components.melissa
+py-melissa-climate==1.0.1
+
 # homeassistant.components.camera.synology
 py-synology==0.1.5
 
diff --git a/tests/components/climate/test_melissa.py b/tests/components/climate/test_melissa.py
new file mode 100644
index 0000000000000000000000000000000000000000..ef5cbff5087faba71df1761c0deda552b2bc69c3
--- /dev/null
+++ b/tests/components/climate/test_melissa.py
@@ -0,0 +1,264 @@
+"""Test for Melissa climate component."""
+import unittest
+from unittest.mock import Mock, patch
+import json
+
+from asynctest import mock
+
+from homeassistant.components.climate import melissa, \
+    SUPPORT_TARGET_TEMPERATURE, SUPPORT_OPERATION_MODE, SUPPORT_ON_OFF, \
+    SUPPORT_FAN_MODE, STATE_HEAT, STATE_FAN_ONLY, STATE_DRY, STATE_COOL, \
+    STATE_AUTO
+from homeassistant.components.fan import SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH
+from homeassistant.components.melissa import DATA_MELISSA
+from homeassistant.const import TEMP_CELSIUS, STATE_ON, ATTR_TEMPERATURE, \
+    STATE_OFF, STATE_IDLE, STATE_UNKNOWN
+from tests.common import get_test_home_assistant, load_fixture
+
+
+class TestMelissa(unittest.TestCase):
+    """Tests for Melissa climate."""
+
+    def setUp(self):  # pylint: disable=invalid-name
+        """Set up test variables."""
+        self.hass = get_test_home_assistant()
+        self._serial = '12345678'
+
+        self.api = Mock()
+        self.api.fetch_devices.return_value = json.loads(load_fixture(
+            'melissa_fetch_devices.json'
+        ))
+        self.api.cur_settings.return_value = json.loads(load_fixture(
+            'melissa_cur_settings.json'
+        ))
+        self.api.status.return_value = json.loads(load_fixture(
+            'melissa_status.json'
+        ))
+        self.api.STATE_OFF = 0
+        self.api.STATE_ON = 1
+        self.api.STATE_IDLE = 2
+
+        self.api.MODE_AUTO = 0
+        self.api.MODE_FAN = 1
+        self.api.MODE_HEAT = 2
+        self.api.MODE_COOL = 3
+        self.api.MODE_DRY = 4
+
+        self.api.FAN_AUTO = 0
+        self.api.FAN_LOW = 1
+        self.api.FAN_MEDIUM = 2
+        self.api.FAN_HIGH = 3
+
+        self.api.STATE = 'state'
+        self.api.MODE = 'mode'
+        self.api.FAN = 'fan'
+        self.api.TEMP = 'temp'
+
+        device = self.api.fetch_devices()[self._serial]
+        self.thermostat = melissa.MelissaClimate(
+            self.api, device['serial_number'], device)
+        self.thermostat.update()
+
+    def tearDown(self):  # pylint: disable=invalid-name
+        """Teardown this test class. Stop hass."""
+        self.hass.stop()
+
+    @patch("homeassistant.components.climate.melissa.MelissaClimate")
+    def test_setup_platform(self, mocked_thermostat):
+        """Test setup_platform."""
+        device = self.api.fetch_devices()[self._serial]
+        thermostat = mocked_thermostat(self.api, device['serial_number'],
+                                       device)
+        thermostats = [thermostat]
+
+        self.hass.data[DATA_MELISSA] = self.api
+
+        config = {}
+        add_devices = Mock()
+        discovery_info = {}
+
+        melissa.setup_platform(self.hass, config, add_devices, discovery_info)
+        add_devices.assert_called_once_with(thermostats)
+
+    def test_get_name(self):
+        """Test name property."""
+        self.assertEqual("Melissa 12345678", self.thermostat.name)
+
+    def test_is_on(self):
+        """Test name property."""
+        self.assertEqual(self.thermostat.is_on, True)
+        self.thermostat._cur_settings = None
+        self.assertEqual(STATE_UNKNOWN, self.thermostat.is_on)
+
+    def test_current_fan_mode(self):
+        """Test current_fan_mode property."""
+        self.thermostat.update()
+        self.assertEqual(SPEED_LOW, self.thermostat.current_fan_mode)
+        self.thermostat._cur_settings = None
+        self.assertEqual(STATE_UNKNOWN, self.thermostat.current_fan_mode)
+
+    def test_current_temperature(self):
+        """Test current temperature."""
+        self.assertEqual(27.4, self.thermostat.current_temperature)
+
+    def test_current_temperature_no_data(self):
+        """Test current temperature without data."""
+        self.thermostat._data = None
+        self.assertIsNone(self.thermostat.current_temperature)
+
+    def test_target_temperature_step(self):
+        """Test current target_temperature_step."""
+        self.assertEqual(1, self.thermostat.target_temperature_step)
+
+    def test_current_operation(self):
+        """Test current operation."""
+        self.thermostat.update()
+        self.assertEqual(self.thermostat.current_operation, STATE_HEAT)
+        self.thermostat._cur_settings = None
+        self.assertEqual(STATE_UNKNOWN, self.thermostat.current_operation)
+
+    def test_operation_list(self):
+        """Test the operation list."""
+        self.assertEqual(
+            [STATE_AUTO, STATE_HEAT, STATE_COOL, STATE_DRY, STATE_FAN_ONLY],
+            self.thermostat.operation_list
+        )
+
+    def test_fan_list(self):
+        """Test the fan list."""
+        self.assertEqual(
+            [STATE_AUTO, SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH],
+            self.thermostat.fan_list
+        )
+
+    def test_target_temperature(self):
+        """Test target temperature."""
+        self.assertEqual(16, self.thermostat.target_temperature)
+        self.thermostat._cur_settings = None
+        self.assertEqual(STATE_UNKNOWN, self.thermostat.target_temperature)
+
+    def test_state(self):
+        """Test state."""
+        self.assertEqual(STATE_ON, self.thermostat.state)
+        self.thermostat._cur_settings = None
+        self.assertEqual(STATE_UNKNOWN, self.thermostat.state)
+
+    def test_temperature_unit(self):
+        """Test temperature unit."""
+        self.assertEqual(TEMP_CELSIUS, self.thermostat.temperature_unit)
+
+    def test_min_temp(self):
+        """Test min temp."""
+        self.assertEqual(16, self.thermostat.min_temp)
+
+    def test_max_temp(self):
+        """Test max temp."""
+        self.assertEqual(30, self.thermostat.max_temp)
+
+    def test_supported_features(self):
+        """Test supported_features property."""
+        features = (SUPPORT_TARGET_TEMPERATURE | SUPPORT_OPERATION_MODE |
+                    SUPPORT_ON_OFF | SUPPORT_FAN_MODE)
+        self.assertEqual(features, self.thermostat.supported_features)
+
+    def test_set_temperature(self):
+        """Test set_temperature."""
+        self.api.send.return_value = True
+        self.thermostat.update()
+        self.assertTrue(self.thermostat.set_temperature(
+            **{ATTR_TEMPERATURE: 25}))
+        self.assertEqual(25, self.thermostat.target_temperature)
+
+    def test_fan_mode(self):
+        """Test set_fan_mode."""
+        self.api.send.return_value = True
+        self.assertTrue(self.thermostat.set_fan_mode(SPEED_LOW))
+        self.assertEqual(SPEED_LOW, self.thermostat.current_fan_mode)
+
+    def test_set_operation_mode(self):
+        """Test set_operation_mode."""
+        self.api.send.return_value = True
+        self.assertTrue(self.thermostat.set_operation_mode(STATE_COOL))
+        self.assertEqual(STATE_COOL, self.thermostat.current_operation)
+
+    def test_turn_on(self):
+        """Test turn_on."""
+        self.assertTrue(self.thermostat.turn_on())
+
+    def test_turn_off(self):
+        """Test turn_off."""
+        self.assertTrue(self.thermostat.turn_off())
+
+    def test_send(self):
+        """Test send."""
+        self.thermostat.update()
+        self.assertTrue(self.thermostat.send(
+            {'fan': self.api.FAN_MEDIUM}))
+        self.assertEqual(SPEED_MEDIUM, self.thermostat.current_fan_mode)
+        self.api.send.return_value = False
+        self.thermostat._cur_settings = None
+        self.assertFalse(self.thermostat.send({
+            'fan': self.api.FAN_LOW}))
+        self.assertNotEquals(SPEED_LOW, self.thermostat.current_fan_mode)
+        self.assertIsNone(self.thermostat._cur_settings)
+
+    @mock.patch('homeassistant.components.climate.melissa._LOGGER.warning')
+    def test_update(self, mocked_warning):
+        """Test update."""
+        self.thermostat.update()
+        self.assertEqual(SPEED_LOW, self.thermostat.current_fan_mode)
+        self.assertEqual(STATE_HEAT, self.thermostat.current_operation)
+        self.thermostat._api.status.side_effect = KeyError('boom')
+        self.thermostat.update()
+        mocked_warning.assert_called_once_with(
+            'Unable to update component %s', self.thermostat.entity_id)
+
+    def test_melissa_state_to_hass(self):
+        """Test for translate melissa states to hass."""
+        self.assertEqual(STATE_OFF, self.thermostat.melissa_state_to_hass(0))
+        self.assertEqual(STATE_ON, self.thermostat.melissa_state_to_hass(1))
+        self.assertEqual(STATE_IDLE, self.thermostat.melissa_state_to_hass(2))
+        self.assertEqual(STATE_UNKNOWN,
+                         self.thermostat.melissa_state_to_hass(3))
+
+    def test_melissa_op_to_hass(self):
+        """Test for translate melissa operations to hass."""
+        self.assertEqual(STATE_AUTO, self.thermostat.melissa_op_to_hass(0))
+        self.assertEqual(STATE_FAN_ONLY, self.thermostat.melissa_op_to_hass(1))
+        self.assertEqual(STATE_HEAT, self.thermostat.melissa_op_to_hass(2))
+        self.assertEqual(STATE_COOL, self.thermostat.melissa_op_to_hass(3))
+        self.assertEqual(STATE_DRY, self.thermostat.melissa_op_to_hass(4))
+        self.assertEqual(
+            STATE_UNKNOWN, self.thermostat.melissa_op_to_hass(5))
+
+    def test_melissa_fan_to_hass(self):
+        """Test for translate melissa fan state to hass."""
+        self.assertEqual(STATE_AUTO, self.thermostat.melissa_fan_to_hass(0))
+        self.assertEqual(SPEED_LOW, self.thermostat.melissa_fan_to_hass(1))
+        self.assertEqual(SPEED_MEDIUM, self.thermostat.melissa_fan_to_hass(2))
+        self.assertEqual(SPEED_HIGH, self.thermostat.melissa_fan_to_hass(3))
+        self.assertEqual(STATE_UNKNOWN, self.thermostat.melissa_fan_to_hass(4))
+
+    @mock.patch('homeassistant.components.climate.melissa._LOGGER.warning')
+    def test_hass_mode_to_melissa(self, mocked_warning):
+        """Test for hass operations to melssa."""
+        self.assertEqual(0, self.thermostat.hass_mode_to_melissa(STATE_AUTO))
+        self.assertEqual(
+            1, self.thermostat.hass_mode_to_melissa(STATE_FAN_ONLY))
+        self.assertEqual(2, self.thermostat.hass_mode_to_melissa(STATE_HEAT))
+        self.assertEqual(3, self.thermostat.hass_mode_to_melissa(STATE_COOL))
+        self.assertEqual(4, self.thermostat.hass_mode_to_melissa(STATE_DRY))
+        self.thermostat.hass_mode_to_melissa("test")
+        mocked_warning.assert_called_once_with(
+            "Melissa have no setting for %s mode", "test")
+
+    @mock.patch('homeassistant.components.climate.melissa._LOGGER.warning')
+    def test_hass_fan_to_melissa(self, mocked_warning):
+        """Test for translate melissa states to hass."""
+        self.assertEqual(0, self.thermostat.hass_fan_to_melissa(STATE_AUTO))
+        self.assertEqual(1, self.thermostat.hass_fan_to_melissa(SPEED_LOW))
+        self.assertEqual(2, self.thermostat.hass_fan_to_melissa(SPEED_MEDIUM))
+        self.assertEqual(3, self.thermostat.hass_fan_to_melissa(SPEED_HIGH))
+        self.thermostat.hass_fan_to_melissa("test")
+        mocked_warning.assert_called_once_with(
+            "Melissa have no setting for %s fan mode", "test")
diff --git a/tests/components/sensor/test_melissa.py b/tests/components/sensor/test_melissa.py
new file mode 100644
index 0000000000000000000000000000000000000000..3a13020438f035448d790ea4b6b8c6fabcaf5968
--- /dev/null
+++ b/tests/components/sensor/test_melissa.py
@@ -0,0 +1,89 @@
+"""Test for Melissa climate component."""
+import unittest
+import json
+from unittest.mock import Mock
+
+from homeassistant.components.melissa import DATA_MELISSA
+from homeassistant.components.sensor import melissa
+from homeassistant.components.sensor.melissa import MelissaTemperatureSensor, \
+    MelissaHumiditySensor
+from homeassistant.const import TEMP_CELSIUS, STATE_UNKNOWN
+from tests.common import get_test_home_assistant, load_fixture
+
+
+class TestMelissa(unittest.TestCase):
+    """Tests for Melissa climate."""
+
+    def setUp(self):  # pylint: disable=invalid-name
+        """Set up test variables."""
+        self.hass = get_test_home_assistant()
+        self._serial = '12345678'
+
+        self.api = Mock()
+        self.api.fetch_devices.return_value = json.loads(load_fixture(
+            'melissa_fetch_devices.json'
+        ))
+        self.api.status.return_value = json.loads(load_fixture(
+            'melissa_status.json'
+        ))
+
+        self.api.TEMP = 'temp'
+        self.api.HUMIDITY = 'humidity'
+        device = self.api.fetch_devices()[self._serial]
+        self.temp = MelissaTemperatureSensor(device, self.api)
+        self.hum = MelissaHumiditySensor(device, self.api)
+
+    def tearDown(self):  # pylint: disable=invalid-name
+        """Teardown this test class. Stop hass."""
+        self.hass.stop()
+
+    def test_setup_platform(self):
+        """Test setup_platform."""
+        self.hass.data[DATA_MELISSA] = self.api
+
+        config = {}
+        add_devices = Mock()
+        discovery_info = {}
+
+        melissa.setup_platform(self.hass, config, add_devices, discovery_info)
+
+    def test_name(self):
+        """Test name property."""
+        device = self.api.fetch_devices()[self._serial]
+        self.assertEqual(self.temp.name, '{0} {1}'.format(
+            device['name'],
+            self.temp._type
+        ))
+        self.assertEqual(self.hum.name, '{0} {1}'.format(
+            device['name'],
+            self.hum._type
+        ))
+
+    def test_state(self):
+        """Test state property."""
+        device = self.api.status()[self._serial]
+        self.temp.update()
+        self.assertEqual(self.temp.state, device[self.api.TEMP])
+        self.hum.update()
+        self.assertEqual(self.hum.state, device[self.api.HUMIDITY])
+
+    def test_unit_of_measurement(self):
+        """Test unit of measurement property."""
+        self.assertEqual(self.temp.unit_of_measurement, TEMP_CELSIUS)
+        self.assertEqual(self.hum.unit_of_measurement, '%')
+
+    def test_update(self):
+        """Test for update."""
+        self.temp.update()
+        self.assertEqual(self.temp.state, 27.4)
+        self.hum.update()
+        self.assertEqual(self.hum.state, 18.7)
+
+    def test_update_keyerror(self):
+        """Test for faulty update."""
+        self.temp._api.status.return_value = {}
+        self.temp.update()
+        self.assertEqual(STATE_UNKNOWN, self.temp.state)
+        self.hum._api.status.return_value = {}
+        self.hum.update()
+        self.assertEqual(STATE_UNKNOWN, self.hum.state)
diff --git a/tests/components/test_melissa.py b/tests/components/test_melissa.py
new file mode 100644
index 0000000000000000000000000000000000000000..e39ceb1add15147444ff9f4aa1b9c93cc44548de
--- /dev/null
+++ b/tests/components/test_melissa.py
@@ -0,0 +1,38 @@
+"""The test for the Melissa Climate component."""
+import unittest
+from tests.common import get_test_home_assistant, MockDependency
+
+from homeassistant.components import melissa
+
+VALID_CONFIG = {
+    "melissa": {
+        "username": "********",
+        "password": "********",
+    }
+}
+
+
+class TestMelissa(unittest.TestCase):
+    """Test the Melissa component."""
+
+    def setUp(self):  # pylint: disable=invalid-name
+        """Initialize the values for this test class."""
+        self.hass = get_test_home_assistant()
+        self.config = VALID_CONFIG
+
+    def tearDown(self):  # pylint: disable=invalid-name
+        """Teardown this test class. Stop hass."""
+        self.hass.stop()
+
+    @MockDependency("melissa")
+    def test_setup(self, mocked_melissa):
+        """Test setting up the Melissa component."""
+        melissa.setup(self.hass, self.config)
+
+        mocked_melissa.Melissa.assert_called_with(
+            username="********", password="********")
+        self.assertIn(melissa.DATA_MELISSA, self.hass.data)
+        self.assertIsInstance(
+            self.hass.data[melissa.DATA_MELISSA], type(
+                mocked_melissa.Melissa())
+        )
diff --git a/tests/fixtures/melissa_cur_settings.json b/tests/fixtures/melissa_cur_settings.json
new file mode 100644
index 0000000000000000000000000000000000000000..9d7fb61533042c61fd7e841f10758bc83bb09f19
--- /dev/null
+++ b/tests/fixtures/melissa_cur_settings.json
@@ -0,0 +1,28 @@
+{
+  "controller": {
+    "id": 1,
+    "user_id": 1,
+    "serial_number": "12345678",
+    "mac": "12345678",
+    "firmware_version": "V1SHTHF",
+    "name": "Melissa 12345678",
+    "type": "melissa",
+    "room_id": null,
+    "created": "2016-07-06 18:59:46",
+    "deleted_at": null,
+    "online": true,
+    "_relation": {
+      "command_log": {
+        "state": 1,
+        "mode": 2,
+        "temp": 16,
+        "fan": 1
+      }
+    }
+  },
+  "_links": {
+    "self": {
+      "href": "/v1/controllers/12345678"
+    }
+  }
+}
diff --git a/tests/fixtures/melissa_fetch_devices.json b/tests/fixtures/melissa_fetch_devices.json
new file mode 100644
index 0000000000000000000000000000000000000000..4b106a613f7b2be36b677f882334c57a23fc46d7
--- /dev/null
+++ b/tests/fixtures/melissa_fetch_devices.json
@@ -0,0 +1,27 @@
+{
+  "12345678": {
+    "user_id": 1,
+    "serial_number": "12345678",
+    "mac": "12345678",
+    "firmware_version": "V1SHTHF",
+    "name": "Melissa 12345678",
+    "type": "melissa",
+    "room_id": null,
+    "created": "2016-07-06 18:59:46",
+    "id": 1,
+    "online": true,
+    "brand_id": 1,
+    "controller_log": {
+      "temp": 27.4,
+      "created": "2018-01-08T21:01:14.281Z",
+      "raw_temperature": 28928,
+      "humidity": 18.7,
+      "raw_humidity": 12946
+    },
+    "_links": {
+      "self": {
+        "href": "/v1/controllers"
+      }
+    }
+  }
+}
diff --git a/tests/fixtures/melissa_status.json b/tests/fixtures/melissa_status.json
new file mode 100644
index 0000000000000000000000000000000000000000..ac240b3df1226e724273a671e8cdb6fc6918185b
--- /dev/null
+++ b/tests/fixtures/melissa_status.json
@@ -0,0 +1,8 @@
+{
+  "12345678": {
+    "temp": 27.4,
+    "raw_temperature": 28928,
+    "humidity": 18.7,
+    "raw_humidity": 12946
+  }
+}