#!/usr/bin/env python3 ''' Wetterstation Server Create a webpage access point to show sensor data Hardware: ESP32 (sensor chip temperature) DS18B20 temperature sensor Sensirion SCD41 CO2 sensor Bosch BME280 MicroPython v1.26.1 on 2025-09-11; Generic ESP32 module with ESP32 External libraries: https://microdot.readthedocs.io/en/latest/intro.html https://github.com/peter-l5/MicroPython_SCD4X https://github.com/robert-hh/BME280 2026-01-22 mchris ''' import network import uasyncio as asyncio from microdot import Microdot import esp32 import machine import onewire import ds18x20 import scd4x import gc import time from bme280_float import * gc.collect() def web_page(): try: with open('index.html', 'r') as f: return f.read() except OSError: # Fallback if file missing return "

index.html not found

" async def ap_mode(ssid, password): print("Free heap before init:", gc.mem_free()) # DS18B20 on GPIO 4 dat = machine.Pin(4) ds = ds18x20.DS18X20(onewire.OneWire(dat)) ds_sensors = ds.scan() print('DS18B20 sensors:', ds_sensors) gc.collect() # SCD41 I2C i2c = machine.I2C(1, scl=machine.Pin(22), sda=machine.Pin(21), freq=100000) scd = scd4x.SCD4X(i2c) print('SCD41 init...') scd.start_periodic_measurement() await asyncio.sleep(5) print('SCD41 ready') gc.collect() bme280 = BME280(i2c=i2c) print(bme280.values) print('bme280 initialized') gc.collect() print("Free heap before WiFi:", gc.mem_free()) # WiFi AP ap = network.WLAN(network.AP_IF) ap.active(True) ap.config(essid=ssid, password=password) while not ap.active(): await asyncio.sleep(0.1) print('AP IP:', ap.ifconfig()[0]) print("Free heap after WiFi:", gc.mem_free()) app = Microdot() app.ds_sensors = ds_sensors app.ds_device = ds app.scd_device = scd app.bme208=bme280 @app.route('/') async def index(request): return web_page(), 200, {'Content-Type': 'text/html'} @app.route('/data') async def get_data(request): # Internal temp temp_raw = esp32.raw_temperature() internal = round((temp_raw - 32) * 5/9, 1) # DS18B20 ds18b20 = -99 if app.ds_sensors: try: app.ds_device.convert_temp() await asyncio.sleep_ms(750) ds18b20 = round(app.ds_device.read_temp(app.ds_sensors[0]), 1) except: pass # SCD41 scd_temp = scd_co2 = scd_rh = -99 try: if app.scd_device.data_ready: scd_temp = round(app.scd_device.temperature, 1) scd_co2 = int(app.scd_device.CO2) scd_rh = round(app.scd_device.relative_humidity, 1) except: pass values=app.bme208.values bme_t=values[0] bme_p=values[1] bme_rh=values[2] gc.collect() t = time.localtime() timestamp = "{:02d}:{:02d}:{:02d}".format(t[3], t[4], t[5]) return { 'internal': internal, 'ds18b20': ds18b20, 'scd_temp': scd_temp, 'scd_co2': scd_co2, 'scd_rh': scd_rh, 'bme_t':bme_p, 'bme_p':bme_t, 'bme_rh':bme_rh, 'time': timestamp }, 200, {'Content-Type': 'application/json'} print("Starting server... Free heap:", gc.mem_free()) await app.start_server(port=80) gc.collect() asyncio.run(ap_mode('pipico', '12345678'))