In case you are a nut case and want everything monitored and under control, as I do, you NEED a temperature and humidity monitoring device that is at least semi-reliable, throwable, checkable, cheap and ugly as fuck.

Also, the results can be seen here: and especially, the graphing for battery state (3rd graph from top):

Search no more, as you have found it, read on and relive the ecstatic feelings of designing an ass-ripping ultra portable ESP8266 powered temperhumi meter for a couple [f|b]ucks.

Da parts.

When it comes to hardware selection, it was an obvious choice. What better a device to find than an ESP8266-12F in it’s all bare guts sticking out. The DHT11 is very inprecise, but cheap and easy to work with. Also, with every unit manufactured – a polar bear dies. Go get ’em. For the other stuff, a few capacitors, some resistors etc…

Heck, I shall put a list of all that shit for this MOFO project just here:

  • ESP8266-12E/F
  • DHT11, or even the more advanced DHT22 would work, I assume
  • battery case for 3x AAA sized batteries (1.2V NiMh preferred)
  • self-made PCB – more on that later
  • 2x10k, 1x2k7 resistors
  • 1x 100nF, 1x10uF capacitors
  • couple pin headers, if you want to have it fancy (DIN 2.54mm)
  • want a case? Get a case then

Da code.

As nobody cares about the hardware part, let’s look at the software part. My choice of language to fit this non-demanding and stupidly ugly project – YEAH! Python. Micro Python that is, as this small thing runs on these small things (i.e. uPython runs on ESP8266). No interrupts, no memory allocations, nothing of the stuff that grown-ups do with microprocessors.

Alright, alright, you expect a chunk of code, copy paste it and move on. Well, here you go then. **slab**

import dht
import machine
import utime
import urequests
import network
import json
import esp
from flashbdev import bdev

# Do we want to measure internal or external? VCC / ADC
# Network credentials pulled from inet.conf residing on the FS
# options check
possible_opts = ['ssid', 'pass', 'ip', 'netmask', 'gw', 'destination', 'dns']
# Let's set location, will be set as a tag in influx
# INFLUX config - can be part of the config file, no?
_INFLUX_PORT = '8086'
_INFLUX_DB = 'indb'
_INFLUX_PASS = 'password'


def set_adc_mode(mode):
    # Switch between internal and external ADC. Returns if restart is needed
    # Mode up in variables
    sector_size = bdev.SEC_SIZE
    flash_size = esp.flash_size() # device dependent
    init_sector = int(flash_size / sector_size - 4)
    data = bytearray(esp.flash_read(init_sector * sector_size, sector_size))
    if data[107] == mode:
        # flash is already correct; nothing to do
        return False
        data[107] = mode  # re-write flash
        esp.flash_write(init_sector * sector_size, data)
        print("ADC mode changed in flash; restart to use it!")
        return True

def check_wake_state():
    # check if the device woke from a deep sleep
    if machine.reset_cause() == machine.DEEPSLEEP_RESET:
        print('woke from a deep sleep')

def deep_sleep(sleep_minutes):
    sleep_ms = sleep_minutes * 60 * 1000
    rtc = machine.RTC()
    rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)
    rtc.alarm(rtc.ALARM0, sleep_ms)

def read_network_config():
    config_dict = {}
        with open('inet.conf', 'r') as conf_handler:
            config = conf_handler.readlines()
            for item in config:
                tmp_list = item.split("=")
                option = tmp_list[0].strip()
                if len(tmp_list) == 2 and option in possible_opts:
                    value = tmp_list[1].strip()
                    config_dict.update({option: value})
    except Exception as e:
        print("WARNING: Errors in INFRA config, still going for AP")
        return False
    return config_dict

def set_up_infra(_SSID, _PASS, _TIMEOUT):
    sta = network.WLAN(network.STA_IF)
    ap = network.WLAN(network.AP_IF)
    print("Disabling AP")
    print("Activating INFRA")
    sta.isconnected() # False, it should be # Comments by Yoda
    print("Connecting to infra")
    sta.connect(_SSID, _PASS)
    connection_tout = _TIMEOUT
    print("Let's wait for the network to come up") # Hopefully not indefinitely
    # That's why we have a nice timeout, so it does not drain the batt on con
    while not (sta.isconnected()):
        if connection_tout > 0:
            print("Trying... {} more times".format(connection_tout))
            connection_tout = connection_tout - 1
            print("Out of retrys while waiting for network, going to sleep")
            return False
    network_config = sta.ifconfig()
    return network_config

Network configuration section
    net_config = read_network_config()
    if net_config:
        net_conf_result = set_up_infra(net_config["ssid"],
        print("ERROR: cannot read from inet.conf file")
    if net_conf_result:
        print("  IP: {}".format(net_conf_result[0]))
        print("  MASK: {}".format(net_conf_result[1]))
        print("  GW: {}".format(net_conf_result[2]))
        print("  DNS: {}\n".format(net_conf_result[3]))
        print("WARNING: Network config not done")
except Exception as e:
    print("ERROR: Network configuration failed with: {}".format(e))
print("Network section done")

Measure temperhumi
print("getting the temperature here")
d1 = machine.Pin(5, machine.Pin.IN)
    local_dht = dht.DHT11(d1)
    temperature = local_dht.temperature()
    humidity = local_dht.humidity()
    print("T: {}".format(temperature))
    print("H: {}".format(humidity))
except Exception as e:
    print("ERROR: Temp measurement: {}".format(e))
    temperature = 255
    humidity = 255

Measure battery
print("Setting ADC mode here")
vcc = machine.ADC(1)
val =
battery =

Data send
if net_conf_result:
    post_str = "http://{}:{}/write?db={}&u={}&p={}"
    post = post_str.format(_INFLUX_HOST,
    data_str = "usense,type={_type} humidity={_humi} \n " + \
                "usense,type={_type} temperature={_temp}\n " + \
                "usense,type={_type} battery={_batt}"
    data = data_str.format(_type=_LOCATION_TYPE,
        result =, data=data)
    except Exception as e:
        print("ERROR: Data send 'urequest': {}".format(e))
        # Go to sleep, cause why the fuck not
    print("WARNING: Not sending data, as infra is not available")
# Sleep, deep. You earned it

So you want a better guide to the hardware part, eh? Wait for it and hold my beer…

How to put it together

You might want to read a couple articles first. namely to see how to flash an ESP and on how to setup micropython on an ESP.