Build a Apple HomeKit Temperature Sensor Device Using a ESP8266 and a BME280





Introduction: Build a Apple HomeKit Temperature Sensor Device Using a ESP8266 and a BME280

In today's instructable, we will be making low cost temperature, humidity and moisture sensor based on either the AOSONG AM2302/DHT22 or BME280 temperature/humidity sensor, YL-69 moisture sensor and the ESP8266/Nodemcu platform. And for displaying the data, we will be using homebridge to integrate to Apple's HomeKit.

This supports multiple devices and device discovery using mDNS, with minimal configuration required in Homebridge.

Parts List

  • NodeMCU / New Wireless module NodeMcu Lua WIFI Internet of Things development board based ESP8266 with pcb Antenna and usb port
    • These are very cheap on Ali Express, only problem is that shipping takes 4-6 weeks
  • Mobile Phone Charger
  • Mini USB Cable
  • AOSONG AM2302/DHT22 temperature/humidity sensor

Or as an alternative sensor

  • Bosch BME280 Temperature, Humidity and Barometric Sensor
  • YL-69 Moisture Sensor
  • 2N3904 Transistor
  • 1K Resistor
    • Transistor and Resistor only needed of YL-69 Moisture Sensor
  • 5 Pin Female to Female cable set ( 1.5' ) ( DHT )
  • 4 Pin Female to Female cable set (1.5') ( BME 280 )
  • Heat shrink tubing small
  • Container to install NodeMCU
    • I used a small plastic food container from dollarama
    • 5 small nuts and bolts for mounting NodeMCU


  • Soldering Iron
  • Solder
  • Wire Cutters

Step 1: Hardware Build - DHT22

Connecting the DHT22

1. Cut the 5 Pin Female to Female cable in half, creating a cable about 9 inches long.

2. On the connecter, pins 2 and 3 are unused and can be removed.

3. Bare about a 1/4" of each wire on the end opposite the connector.

4. With your soldering iron, tin each wire end and the terminals on the DHT22.

5. Cut about 3/4" of heat shrink tubing and push down the wires.

6. Solder the wires to the DHT22 as follows

Connecter Pin --> DHT22 Pin

1 ---> 2 ( Second from left )

4 ---> 1 ( First on the left )

5 ---> 4 ( First on the right )

7. Slide the heat shrink tubing over the DHT22 Pins and shrink the tubing with the soldering iron.

Step 2: Hardware Build - BME280

Connecting the BME280

1. Cut the 4 Pin Female to Female cable in half, creating a cable about 9 inches long.

2. Bare about a 1/4" of each wire on the end opposite the connector.

3. With your soldering iron, tin each wire end.

4. Solder the wires to the BME280 in this order, VCC, GND, SCL, SDA. These need to line up to pins in the connector.

Step 3: Hardware Build - YL-69

Step 4: Build Case

Step 5: Build NodeMCU Firmware

1. Using, create a custom firmware containing at least these modules:


2. Please use esptool to install the float firmware onto your nodemcu. There are alot of guides for this, so I won't repeat it here.

Step 6: Connect Sensors


1. Position cable connector so that pin 1 connects to D2 on nodemcu, pin 4 with 3v3 and pin 5 with gnu.


1. Connect the BME280 to the nodeMCO, lining up the pins as follows:

3V3 -> VCC


D5 -> SCL

D6 -> SDA

Step 7: Install Nodemcu Software

1. Download lua software package from

2. Follow the installation instructions in the README located here

Step 8: Testing

1. You can test from the command line with curl or wget, make sure you use the ip address from the Esplorer screen and not mine ;-)

{ "Hostname": "NODE-8689D", "Model": "BME", "Version": "1.2", "Data": {"Temperature": 22.15, "Humidity": 50.453, "Moisture": 8, "Status": 0, "Barometer": 1003.185, "Dew": 11.38 }}

2. In Esplorer you should see the following

GET / HTTP/1.1<br>Host:
User-Agent: curl/7.43.0
Accept: */*
Status: 0
Temp: 22.15
Humi: 50.453
Moisture: 8
Baro: 1003.185
Dew: 11.38

3. Using Esplorer install init.lua. The nodemcu portion of the build is now complete.

4. To test mDNS, I use this command on OS X

dns-sd -B _dht22._tcp

And for the 2 devices on the network, I receive the following output:

Browsing for _dht22._tcp
DATE: ---Mon 19 Sep 2016---
21:11:26.737  ...STARTING...
Timestamp     A/R    Flags  if Domain               Service Type         Instance Name
21:11:26.739  Add        3   4 local.               _dht22._tcp.         NODE-18A6B3
21:11:26.739  Add        2   4 local.               _dht22._tcp.         NODE-871ED8

Step 9: Homebridge-mcuiot Install

1. Install homebridge using:

npm install -g homebridge

I won't go into a lot of details around the initial install of homebridge and how to configure it to autostart etc. Their are a lot of other guides for this.

2. Install homebridge-mcuiot using:

npm install -g homebridge-mcuiot

3. Update your configuration file, see sample-config.json in this directory.


"bridge": {<br>        "name": "Bart",
        "username": "CC:22:3D:E3:CD:39",
        "port": 51826,
        "pin": "031-45-154"
    "description": "HomeBridge",
"platforms": [
    { "platform":   "mcuiot",
       "name": "mcuiot" }
"accessories": [ ]

4. Start homebridge, output should look like this

[10/20/2016, 10:15:20 PM] Loaded plugin: homebridge-mcuiot<br>
[10/20/2016, 10:15:20 PM] Registering platform 'homebridge-mcuiot.mcuiot'
[10/20/2016, 10:15:20 PM] ---
[10/20/2016, 10:15:20 PM] Loaded config.json with 0 accessories and 0 platforms.
[10/20/2016, 10:15:20 PM] ---
[10/20/2016, 10:15:20 PM] Loading 0 platforms...
[10/20/2016, 10:15:20 PM] Loading 0 accessories...
Load homebridge-mcuiot.mcuiot
Scan this code with your HomeKit App on your iOS device to pair with Homebridge:
    │ 031-45-154 │     
[10/20/2016, 10:15:20 PM] [homebridge-mcuiot.mcuiot] Starting mDNS listener
[10/20/2016, 10:15:20 PM] Homebridge is running on port 51826.
[10/20/2016, 10:15:20 PM] [homebridge-mcuiot.mcuiot] Found url <a href="http://NODE-871ED8.local.:80/" rel="nofollow">  http://NODE-871ED8.local.:80/>
[10/20/2016, 10:15:20 PM] [homebridge-mcuiot.mcuiot] Found url <a href="http://NODE-869815.local.:80/" rel="nofollow">  http://NODE-869815.local.:80/>
[10/20/2016, 10:15:20 PM] [homebridge-mcuiot.mcuiot] Found url <a href="http://NODE-8689D.local.:80/" rel="nofollow">  http://NODE-8689D.local.:80/>
[10/20/2016, 10:15:21 PM] [homebridge-mcuiot.mcuiot] addMcuAccessory 195 NODE-8689D BME
[10/20/2016, 10:15:21 PM] [homebridge-mcuiot.mcuiot] addMcuAccessory 195 NODE-871ED8 DHT
[10/20/2016, 10:15:21 PM] [homebridge-mcuiot.mcuiot] addMcuAccessory 195 NODE-869815 DHT

In my environment I have 3 devices running.

Step 10: Homebridge

On your iPhone/iPad start your favourite homekit client and pair you client to homebridge. You should see all the mcuiot devices.

Adding devices

Devices are auto discovered using mDNS, and will add new devices when they appear on mDNS. In the event that devices are not discovered, restarting homebridge will trigger a reconciliation between the plugin and mDNS, and add missing devices. Missing devices are not removed during startup, see below for how to remove non-existent devices.

Removing devices

Devices are removed using the 'Identify Accessory' function. When you use the function from your app, it checks to see if the device is truly not responding then removes the device.



    • Science of Cooking

      Science of Cooking
    • Pocket-Sized Contest

      Pocket-Sized Contest
    • Trash to Treasure

      Trash to Treasure

    We have a be nice policy.
    Please be positive and constructive.




    Hello! I really hope you can help me with my problems trying this out. First i had problems using your scripts, as you have added "garagedooropener" script, which needed something i did not have. But i solved this by removing those scripts from "test.lua" so id did not try to call them. But now i keep getting errors as it is trying to call "config.lua" and i think maybe i have problems in adding my wifi said and password too, as it is not exactly as your guide anymore, i think. I hope you can follow my problems, and here is my last try at starting the server.

    > file.remove("test.lua");"test.lua","w+");

    > w = file.writelinew([[]]);w([[config = require("config")]]);w([[print("Heap Available: -c " .. node.heap())]]);w([[led = require("led")]]);w([[print("Heap Available: -l " .. node.heap())]]);w([[bme = require("bme")]]);w([[print("Heap Available: -b " .. node.heap())]]);w([[app = require("main")]]);

    > w([[print("Heap Available: -m " .. node.heap())]]);w([[setup = require("setup")]]);w([[print("Heap Available: -setup " .. node.heap())]]);w([[led.boot()]]);w([[print("Heap Available: -boot " .. node.heap())]]);w([[setup.start()]]);w([[print("Heap Available: -start " .. node.heap())]]);w([[-- Never gets here]]);file.close();dofile("test.lua");

    Heap Available: -c 23912

    Heap Available: -l 24928

    Heap Available: -b 24928

    Heap Available: -m 24928

    Heap Available: -setup 24928


    Heap Available: -boot 24984

    Setting Init Timer

    Configuring Wifi ...

    Heap Available: -start 24688

    > PANIC: unprotected error in call to Lua API (setup.lua:37: bad argument #1 to 'config' (config table not found!))

    ets Jan 8 2013,rst cause:2, boot mode:(3,6)

    load 0x40100000, len 26772, room 16

    tail 4

    chksum 0x74

    load 0x3ffe8000, len 2192, room 4

    tail 12

    chksum 0x91

    ho 0 tail 12 room 4

    load 0x3ffe8890, len 136, room 12

    tail 12

    chksum 0x75

    csum 0x75

    ����o�r��g|�dldl b��|{�l�o��o�l ��{�l�l�d`��;�d�d�$`��s�l���$l {$��sl���c��cp<cx���x���c��n�ng�l$��lDŽd��d����l�{sd�g����b$l��#���cl�crd;

    NodeMCU custom build by

    branch: master

    commit: 2e67ff5a639a13260fd4fb3c3b627ccdc2845616

    SSL: false

    modules: adc,bit,bme280,dht,file,gpio,mdns,net,node,tmr,uart,wifi

    build built on: 2017-10-07 11:12

    powered by Lua 5.1.4 on SDK 2.1.0(116b762)

    That error at setup.lua is definitely caused the wifi passwords section not being correct. I would suggest that you try to reformat the config.lua line again. It should look like this

    module.SSID["Network Name"] = { ssid="Network Name", pwd = "password" }

    If your SSID was linksys and the password was computer, it would look like this.

    module.SSID["linksys"] = { ssid="linksys", pwd = "computer" }

    Also to remove the Garage door sensor, comment out the gd= line in init.lua and you don't need to install ads1115.lua.

    PS In github I have made some minor tweaks, that externalize the wifi password to a separate file and other changes. I also just tested with a new nodemcu and BME280. You don't need to update to this version.

    And with that, all my problems were solved! I had to upgrade to your latest scripts, and even then is still said error in calling "config", but i just tried to boot it up a couple of times, and suddenly it worked. Now to make af custom case for it. I'm, thinking some form of Cement enclosure, polished and then treated with some clear coating. Thanks a lot for the help!

    regarding the bme interface change, I saw that yesterday as well and have added it to my todo list for the future. It would only impact you, if you build a new firmware, with the existing firmware no issues.

    Re cases, my go to has been small plastic cases from the dollar store. Cheap and easy to use. I have been thinking about getting a 3D printer, but haven’t made that leap yet.

    Well, a 3D printer is also on my to-buy list! And i can definitely see the appeal for those easily obtainable/moddable plastic containers, but this is all for the WAF score right? ;-)

    On another note: I have been sending Curl command to the Nodemcu a couple of times now, and unfortunately i must say i am rather disappointed in the accuracy compared to my weather station standing right next to it. While my weather station reports a temp. of 17.2 celcius, the BME280 reports 20.16 celsius. Also, the relative humidity on my weather station says 50%, while the BME280 reports 67%. I will try in the future to compare the BME280 with some other weather stations.

    Oh, and i dont know if this has any importance to you, but is says the BME280.init has been replaced with BME280.setup.

    Warning, deprecated API! bme280.init() is replaced by bme280.setup(). It will be removed in the next version. See documentation for details.

    Status: 0

    Temp: 21.99

    Humi: 78.68

    Moisture: 4

    Baro: 1003.893

    Dew: 18.12

    I can see temp & Hum in webserver pages (
    I see the accessories in IPHONE but it didnt show data. It show always 0 C°.
    here my config.json:

    "accessories": [


    "accessory": "HomeMeteo",

    "name": "Meteostation",

    "url": "",

    "temp_url": "/temp",

    "humi_url": "/humidity",

    "light_url": "/light",

    "freq": 1000



    anyone can help me? thanks !

    This doesn’t look like my plugin, I think you posted in the wrong location.


    What am I doing wrong this time? the only accessory I'm getting in HomeApp is MCU-IOT reset switch for some reason :/



    The error you showed from homebridge is a timeout when trying to reach your nodemcu device. It looks like it was seen and discovered, but when it was queried by the plugin the request timed out. Is the nodemcu working okay, was there any errors on its console?