diff --git a/.coveragerc b/.coveragerc
index 0c7f17f3098630816fb22aa37191e7538f5bd0c3..edf66c6252b3d55ad07b5dea3ceba3472f03c97b 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -335,6 +335,7 @@ omit =
     homeassistant/components/sensor/dovado.py
     homeassistant/components/sensor/dte_energy_bridge.py
     homeassistant/components/sensor/ebox.py
+    homeassistant/components/sensor/eddystone_temperature.py
     homeassistant/components/sensor/eliqonline.py
     homeassistant/components/sensor/emoncms.py
     homeassistant/components/sensor/fastdotcom.py
diff --git a/homeassistant/components/sensor/eddystone_temperature.py b/homeassistant/components/sensor/eddystone_temperature.py
new file mode 100644
index 0000000000000000000000000000000000000000..de51ff0d373bd82451ac81df729249f8571a2e1c
--- /dev/null
+++ b/homeassistant/components/sensor/eddystone_temperature.py
@@ -0,0 +1,189 @@
+"""Read temperature information from Eddystone beacons.
+
+Your beacons must be configured to transmit UID (for identification) and TLM
+(for temperature) frames.
+
+For more details about this platform, please refer to the documentation at
+https://home-assistant.io/components/sensor.eddystone_temperature/
+
+Original version of this code (for Skybeacons) by anpetrov.
+https://github.com/anpetrov/skybeacon
+"""
+import logging
+
+import voluptuous as vol
+
+import homeassistant.helpers.config_validation as cv
+from homeassistant.helpers.entity import Entity
+from homeassistant.components.sensor import PLATFORM_SCHEMA
+from homeassistant.const import (
+    CONF_NAME, TEMP_CELSIUS, STATE_UNKNOWN, EVENT_HOMEASSISTANT_STOP,
+    EVENT_HOMEASSISTANT_START)
+
+REQUIREMENTS = ['beacontools[scan]==1.0.1']
+
+_LOGGER = logging.getLogger(__name__)
+
+# constants
+CONF_BEACONS = 'beacons'
+CONF_BT_DEVICE_ID = 'bt_device_id'
+CONF_INSTANCE = 'instance'
+CONF_NAMESPACE = 'namespace'
+
+BEACON_SCHEMA = vol.Schema({
+    vol.Required(CONF_NAMESPACE): cv.string,
+    vol.Required(CONF_INSTANCE): cv.string,
+    vol.Optional(CONF_NAME): cv.string
+})
+
+PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
+    vol.Optional(CONF_BT_DEVICE_ID, default=0): cv.positive_int,
+    vol.Required(CONF_BEACONS): vol.Schema({cv.string: BEACON_SCHEMA}),
+})
+
+
+# pylint: disable=unused-argument
+def setup_platform(hass, config, add_devices, discovery_info=None):
+    """Validate configuration, create devices and start monitoring thread."""
+    _LOGGER.debug("Setting up...")
+
+    bt_device_id = config.get("bt_device_id")
+
+    beacons = config.get("beacons")
+    devices = []
+
+    for dev_name, properties in beacons.items():
+        namespace = get_from_conf(properties, "namespace", 20)
+        instance = get_from_conf(properties, "instance", 12)
+        name = properties.get(CONF_NAME, dev_name)
+
+        if instance is None or namespace is None:
+            _LOGGER.error("Skipping %s", dev_name)
+            continue
+        else:
+            devices.append(EddystoneTemp(name, namespace, instance))
+
+    if len(devices) > 0:
+        mon = Monitor(hass, devices, bt_device_id)
+
+        def monitor_stop(_service_or_event):
+            """Stop the monitor thread."""
+            _LOGGER.info("Stopping scanner for eddystone beacons")
+            mon.stop()
+
+        def monitor_start(_service_or_event):
+            """Start the monitor thread."""
+            _LOGGER.info("Starting scanner for eddystone beacons")
+            mon.start()
+
+        add_devices(devices)
+        mon.start()
+        hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, monitor_stop)
+        hass.bus.listen_once(EVENT_HOMEASSISTANT_START, monitor_start)
+    else:
+        _LOGGER.warning("No devices were added")
+
+
+def get_from_conf(config, config_key, length):
+    """Retrieve value from config and validate length."""
+    string = config.get(config_key)
+    if len(string) != length:
+        _LOGGER.error("Error in config parameter \"%s\": Must be exactly %d "
+                      "bytes. Device will not be added.",
+                      config_key, length/2)
+        return None
+    else:
+        return string
+
+
+class EddystoneTemp(Entity):
+    """Representation of a temperature sensor."""
+
+    def __init__(self, name, namespace, instance):
+        """Initialize a sensor."""
+        self._name = name
+        self.namespace = namespace
+        self.instance = instance
+        self.bt_addr = None
+        self.temperature = STATE_UNKNOWN
+
+    @property
+    def name(self):
+        """Return the name of the sensor."""
+        return self._name
+
+    @property
+    def state(self):
+        """Return the state of the device."""
+        return self.temperature
+
+    @property
+    def unit_of_measurement(self):
+        """Return the unit the value is expressed in."""
+        return TEMP_CELSIUS
+
+    @property
+    def should_poll(self):
+        """Hass should not poll for state."""
+        return False
+
+
+class Monitor(object):
+    """Continously scan for BLE advertisements."""
+
+    def __init__(self, hass, devices, bt_device_id):
+        """Construct interface object."""
+        self.hass = hass
+
+        # list of beacons to monitor
+        self.devices = devices
+        # number of the bt device (hciX)
+        self.bt_device_id = bt_device_id
+
+        def callback(bt_addr, _, packet, additional_info):
+            """Callback for new packets."""
+            self.process_packet(additional_info['namespace'],
+                                additional_info['instance'],
+                                packet.temperature)
+
+        # pylint: disable=import-error
+        from beacontools import (BeaconScanner, EddystoneFilter,
+                                 EddystoneTLMFrame)
+        # Create a device filter for each device
+        device_filters = [EddystoneFilter(d.namespace, d.instance)
+                          for d in devices]
+
+        self.scanner = BeaconScanner(callback, bt_device_id, device_filters,
+                                     EddystoneTLMFrame)
+        self.scanning = False
+
+    def start(self):
+        """Continously scan for BLE advertisements."""
+        if not self.scanning:
+            self.scanner.start()
+            self.scanning = True
+        else:
+            _LOGGER.debug("Warning: start() called, but scanner is already"
+                          " running")
+
+    def process_packet(self, namespace, instance, temperature):
+        """Assign temperature to hass device."""
+        _LOGGER.debug("Received temperature for <%s,%s>: %d",
+                      namespace, instance, temperature)
+
+        for dev in self.devices:
+            if dev.namespace == namespace and dev.instance == instance:
+                if dev.temperature != temperature:
+                    dev.temperature = temperature
+                    dev.schedule_update_ha_state()
+
+    def stop(self):
+        """Signal runner to stop and join thread."""
+        if self.scanning:
+            _LOGGER.debug("Stopping...")
+            self.scanner.stop()
+            _LOGGER.debug("Stopped")
+            self.scanning = False
+        else:
+            _LOGGER.debug("Warning: stop() called but scanner was not"
+                          " running.")
diff --git a/requirements_all.txt b/requirements_all.txt
index 8cb9cf2fa3b806b247d21f170c8e14d199022c45..b656daf4a115ed25bdd38756d8212bdddb2c5951 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -69,6 +69,9 @@ astral==1.4
 # homeassistant.components.sensor.linux_battery
 batinfo==0.4.2
 
+# homeassistant.components.sensor.eddystone_temperature
+# beacontools[scan]==1.0.1
+
 # homeassistant.components.device_tracker.linksys_ap
 # homeassistant.components.sensor.scrape
 beautifulsoup4==4.5.3
diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py
index 16493dc884ecb5ca9e188cfc112a76d0aa789417..94635a585251b4df999603fe21d5a4008262f23c 100755
--- a/script/gen_requirements_all.py
+++ b/script/gen_requirements_all.py
@@ -13,6 +13,7 @@ COMMENT_REQUIREMENTS = (
     'Adafruit_BBIO',
     'fritzconnection',
     'pybluez',
+    'beacontools',
     'bluepy',
     'python-lirc',
     'gattlib',