diff --git a/.coveragerc b/.coveragerc
index ae71a10f73d33e158ec2b77841a1e441b69d3c09..4db8323c3a1157b64ad006840854b6f46a499695 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -340,7 +340,6 @@ omit =
     homeassistant/components/sensor/lastfm.py
     homeassistant/components/sensor/linux_battery.py
     homeassistant/components/sensor/loopenergy.py
-    homeassistant/components/sensor/mhz19.py
     homeassistant/components/sensor/miflora.py
     homeassistant/components/sensor/modem_callerid.py
     homeassistant/components/sensor/mqtt_room.py
diff --git a/homeassistant/components/sensor/mhz19.py b/homeassistant/components/sensor/mhz19.py
index 2ca15898b1878d98e97c2de0213678eea78bd079..816b7465f8fb161706e4c5f993449b64128f5bdb 100644
--- a/homeassistant/components/sensor/mhz19.py
+++ b/homeassistant/components/sensor/mhz19.py
@@ -5,25 +5,40 @@ For more details about this platform, please refer to the documentation at
 https://home-assistant.io/components/sensor.mhz19/
 """
 import logging
+from datetime import timedelta
 
 import voluptuous as vol
 
-from homeassistant.const import CONF_NAME
+from homeassistant.const import (
+    ATTR_TEMPERATURE, CONF_NAME, CONF_MONITORED_CONDITIONS, TEMP_FAHRENHEIT)
 from homeassistant.helpers.entity import Entity
 import homeassistant.helpers.config_validation as cv
 from homeassistant.components.sensor import PLATFORM_SCHEMA
+from homeassistant.util.temperature import celsius_to_fahrenheit
+from homeassistant.util import Throttle
 
-REQUIREMENTS = ['pmsensor==0.3']
+REQUIREMENTS = ['pmsensor==0.4']
 
 _LOGGER = logging.getLogger(__name__)
 
 CONF_SERIAL_DEVICE = 'serial_device'
+MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=10)
 
 DEFAULT_NAME = 'CO2 Sensor'
 
+ATTR_CO2_CONCENTRATION = 'co2_concentration'
+
+SENSOR_TEMPERATURE = 'temperature'
+SENSOR_CO2 = 'co2'
+SENSOR_TYPES = {
+    SENSOR_TEMPERATURE: ['Temperature', None],
+    SENSOR_CO2: ['CO2', 'ppm']
+}
 PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
     vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
     vol.Required(CONF_SERIAL_DEVICE): cv.string,
+    vol.Optional(CONF_MONITORED_CONDITIONS, default=[SENSOR_CO2]):
+        vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]),
 })
 
 
@@ -37,50 +52,96 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
         _LOGGER.error("Could not open serial connection to %s (%s)",
                       config.get(CONF_SERIAL_DEVICE), err)
         return False
+    SENSOR_TYPES[SENSOR_TEMPERATURE][1] = hass.config.units.temperature_unit
+
+    data = MHZClient(co2sensor, config.get(CONF_SERIAL_DEVICE))
+    dev = []
+    name = config.get(CONF_NAME)
+
+    for variable in config[CONF_MONITORED_CONDITIONS]:
+        dev.append(
+            MHZ19Sensor(data, variable, SENSOR_TYPES[variable][1], name))
 
-    dev = MHZ19Sensor(config.get(CONF_SERIAL_DEVICE), config.get(CONF_NAME))
-    add_devices([dev])
+    add_devices(dev, True)
+    return True
 
 
 class MHZ19Sensor(Entity):
     """Representation of an CO2 sensor."""
 
-    def __init__(self, serial_device, name):
+    def __init__(self, mhz_client, sensor_type, temp_unit, name):
         """Initialize a new PM sensor."""
+        self._mhz_client = mhz_client
+        self._sensor_type = sensor_type
+        self._temp_unit = temp_unit
         self._name = name
-        self._state = None
-        self._serial = serial_device
+        self._unit_of_measurement = SENSOR_TYPES[sensor_type][1]
+        self._ppm = None
+        self._temperature = None
 
     @property
     def name(self):
         """Return the name of the sensor."""
-        return self._name
+        return '{}: {}'.format(self._name, SENSOR_TYPES[self._sensor_type][0])
 
     @property
     def state(self):
         """Return the state of the sensor."""
-        return self._state
+        return self._ppm if self._sensor_type == SENSOR_CO2 \
+            else self._temperature
 
     @property
     def unit_of_measurement(self):
         """Return the unit of measurement of this entity, if any."""
-        return "ppm"
+        return self._unit_of_measurement
 
     def update(self):
         """Read from sensor and update the state."""
-        from pmsensor import co2sensor
+        self._mhz_client.update()
+        data = self._mhz_client.data
+        self._temperature = data.get(SENSOR_TEMPERATURE)
+        if self._temperature is not None and \
+                self._temp_unit == TEMP_FAHRENHEIT:
+            self._temperature = round(
+                celsius_to_fahrenheit(self._temperature), 1)
+        self._ppm = data.get(SENSOR_CO2)
 
-        _LOGGER.debug("Reading data from CO2 sensor")
+    @property
+    def device_state_attributes(self):
+        """Return the state attributes."""
+        result = {}
+        if self._sensor_type == SENSOR_TEMPERATURE and self._ppm is not None:
+            result[ATTR_CO2_CONCENTRATION] = self._ppm
+        if self._sensor_type == SENSOR_CO2 and self._temperature is not None:
+            result[ATTR_TEMPERATURE] = self._temperature
+        return result
+
+
+class MHZClient(object):
+    """Get the latest data from the DHT sensor."""
+
+    def __init__(self, co2sensor, serial):
+        """Initialize the sensor."""
+        self.co2sensor = co2sensor
+        self._serial = serial
+        self.data = dict()
+
+    @Throttle(MIN_TIME_BETWEEN_UPDATES)
+    def update(self):
+        """Get the latest data the MH-Z19 sensor."""
+        self.data = {}
         try:
-            ppm = co2sensor.read_mh_z19(self._serial)
-            # values from sensor can only between 0 and 5000
-            if (ppm >= 0) & (ppm <= 5000):
-                self._state = ppm
+            result = self.co2sensor.read_mh_z19_with_temperature(self._serial)
+            if result is None:
+                return
+            co2, temperature = result
+
         except OSError as err:
             _LOGGER.error("Could not open serial connection to %s (%s)",
                           self._serial, err)
             return
 
-    def should_poll(self):
-        """Sensor needs polling."""
-        return True
+        if temperature is not None:
+            self.data[SENSOR_TEMPERATURE] = temperature
+        if co2 is not None and 0 < co2 <= 5000:
+            self.data[SENSOR_CO2] = co2
diff --git a/homeassistant/components/sensor/serial_pm.py b/homeassistant/components/sensor/serial_pm.py
index 9704991e9595cccbcdd5c19b93d07488bedc79ee..a031f9cbd5647e87285fee3eb6cdd961ab6f377e 100644
--- a/homeassistant/components/sensor/serial_pm.py
+++ b/homeassistant/components/sensor/serial_pm.py
@@ -13,7 +13,7 @@ from homeassistant.helpers.entity import Entity
 import homeassistant.helpers.config_validation as cv
 from homeassistant.components.sensor import PLATFORM_SCHEMA
 
-REQUIREMENTS = ['pmsensor==0.3']
+REQUIREMENTS = ['pmsensor==0.4']
 
 _LOGGER = logging.getLogger(__name__)
 
diff --git a/requirements_all.txt b/requirements_all.txt
index 32f5cb57a88279753c576afcd96214a62fe026cc..26169f838eb37b00c3324abf7e977aabbdd89471 100755
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -412,7 +412,7 @@ plexapi==2.0.2
 
 # homeassistant.components.sensor.mhz19
 # homeassistant.components.sensor.serial_pm
-pmsensor==0.3
+pmsensor==0.4
 
 # homeassistant.components.climate.proliphix
 proliphix==0.4.1
diff --git a/tests/components/sensor/test_mhz19.py b/tests/components/sensor/test_mhz19.py
new file mode 100644
index 0000000000000000000000000000000000000000..4311493ac97bcdce21d6b273377133e44e8f507a
--- /dev/null
+++ b/tests/components/sensor/test_mhz19.py
@@ -0,0 +1,122 @@
+"""Tests for MH-Z19 sensor."""
+import unittest
+from unittest.mock import patch, DEFAULT, Mock
+
+from homeassistant.bootstrap import setup_component
+from homeassistant.components.sensor import DOMAIN
+import homeassistant.components.sensor.mhz19 as mhz19
+from homeassistant.const import TEMP_FAHRENHEIT
+from tests.common import get_test_home_assistant, assert_setup_component
+
+
+class TestMHZ19Sensor(unittest.TestCase):
+    """Test the MH-Z19 sensor."""
+
+    hass = None
+
+    def setup_method(self, method):
+        """Setup things to be run when tests are started."""
+        self.hass = get_test_home_assistant()
+
+    def teardown_method(self, method):
+        """Stop everything that was started."""
+        self.hass.stop()
+
+    def test_setup_missing_config(self):
+        """Test setup with configuration missing required entries."""
+        with assert_setup_component(0):
+            assert setup_component(self.hass, DOMAIN, {
+                'sensor': {'platform': 'mhz19'}})
+
+    @patch('pmsensor.co2sensor.read_mh_z19', side_effect=OSError('test error'))
+    def test_setup_failed_connect(self, mock_co2):
+        """Test setup when connection error occurs."""
+        self.assertFalse(mhz19.setup_platform(self.hass, {
+            'platform': 'mhz19',
+            mhz19.CONF_SERIAL_DEVICE: 'test.serial',
+            }, None))
+
+    def test_setup_connected(self):
+        """Test setup when connection succeeds."""
+        with patch.multiple('pmsensor.co2sensor', read_mh_z19=DEFAULT,
+                            read_mh_z19_with_temperature=DEFAULT):
+            from pmsensor.co2sensor import read_mh_z19_with_temperature
+            read_mh_z19_with_temperature.return_value = None
+            mock_add = Mock()
+            self.assertTrue(mhz19.setup_platform(self.hass, {
+                'platform': 'mhz19',
+                'monitored_conditions': ['co2', 'temperature'],
+                mhz19.CONF_SERIAL_DEVICE: 'test.serial',
+                }, mock_add))
+        self.assertEqual(1, mock_add.call_count)
+
+    @patch('pmsensor.co2sensor.read_mh_z19_with_temperature',
+           side_effect=OSError('test error'))
+    def test_client_update_oserror(self, mock_function):
+        """Test MHZClient when library throws OSError."""
+        from pmsensor import co2sensor
+        client = mhz19.MHZClient(co2sensor, 'test.serial')
+        client.update()
+        self.assertEqual({}, client.data)
+
+    @patch('pmsensor.co2sensor.read_mh_z19_with_temperature',
+           return_value=(5001, 24))
+    def test_client_update_ppm_overflow(self, mock_function):
+        """Test MHZClient when ppm is too high."""
+        from pmsensor import co2sensor
+        client = mhz19.MHZClient(co2sensor, 'test.serial')
+        client.update()
+        self.assertIsNone(client.data.get('co2'))
+
+    @patch('pmsensor.co2sensor.read_mh_z19_with_temperature',
+           return_value=(1000, 24))
+    def test_client_update_good_read(self, mock_function):
+        """Test MHZClient when ppm is too high."""
+        from pmsensor import co2sensor
+        client = mhz19.MHZClient(co2sensor, 'test.serial')
+        client.update()
+        self.assertEqual({'temperature': 24, 'co2': 1000}, client.data)
+
+    @patch('pmsensor.co2sensor.read_mh_z19_with_temperature',
+           return_value=(1000, 24))
+    def test_co2_sensor(self, mock_function):
+        """Test CO2 sensor."""
+        from pmsensor import co2sensor
+        client = mhz19.MHZClient(co2sensor, 'test.serial')
+        sensor = mhz19.MHZ19Sensor(client, mhz19.SENSOR_CO2, None, 'name')
+        sensor.update()
+
+        self.assertEqual('name: CO2', sensor.name)
+        self.assertEqual(1000, sensor.state)
+        self.assertEqual('ppm', sensor.unit_of_measurement)
+        self.assertTrue(sensor.should_poll)
+        self.assertEqual({'temperature': 24}, sensor.device_state_attributes)
+
+    @patch('pmsensor.co2sensor.read_mh_z19_with_temperature',
+           return_value=(1000, 24))
+    def test_temperature_sensor(self, mock_function):
+        """Test temperature sensor."""
+        from pmsensor import co2sensor
+        client = mhz19.MHZClient(co2sensor, 'test.serial')
+        sensor = mhz19.MHZ19Sensor(
+            client, mhz19.SENSOR_TEMPERATURE, None, 'name')
+        sensor.update()
+
+        self.assertEqual('name: Temperature', sensor.name)
+        self.assertEqual(24, sensor.state)
+        self.assertEqual('°C', sensor.unit_of_measurement)
+        self.assertTrue(sensor.should_poll)
+        self.assertEqual(
+            {'co2_concentration': 1000}, sensor.device_state_attributes)
+
+    @patch('pmsensor.co2sensor.read_mh_z19_with_temperature',
+           return_value=(1000, 24))
+    def test_temperature_sensor_f(self, mock_function):
+        """Test temperature sensor."""
+        from pmsensor import co2sensor
+        client = mhz19.MHZClient(co2sensor, 'test.serial')
+        sensor = mhz19.MHZ19Sensor(
+            client, mhz19.SENSOR_TEMPERATURE, TEMP_FAHRENHEIT, 'name')
+        sensor.update()
+
+        self.assertEqual(75.2, sensor.state)