
ESP8266 + SHT30
↓
连接 WiFi
↓
浏览器查看温湿度
↓
网页 OTA 更新固件
↓
后续再加信息推送
后续添加对接天猫精灵的功能和空调联动功能
南方天气阴冷潮湿,墙体发霉





上代码
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
#include <ESP8266mDNS.h>
#include <Wire.h>
#define SHT30_ADDR 0x44
const char* ssid = "home-wifi";
const char* password = "123456";
// 网页 OTA 登录账号密码
const char* otaUser = "admin";
const char* otaPass = "admin123456";
ESP8266WebServer server(80);
ESP8266HTTPUpdateServer httpUpdater;
float temperature = 0.0;
float humidity = 0.0;
bool sht30Ok = false;
uint8_t crc8(const uint8_t *data, int len) {
uint8_t crc = 0xFF;
for (int i = 0; i < len; i++) {
crc ^= data[i];
for (int j = 0; j < 8; j++) {
if (crc & 0x80) {
crc = (crc << 1) ^ 0x31;
} else {
crc <<= 1;
}
}
}
return crc;
}
bool readSHT30() {
Wire.beginTransmission(SHT30_ADDR);
Wire.write(0x2C);
Wire.write(0x06);
uint8_t error = Wire.endTransmission();
if (error != 0) {
return false;
}
delay(20);
Wire.requestFrom(SHT30_ADDR, 6);
if (Wire.available() != 6) {
return false;
}
uint8_t data[6];
for (int i = 0; i < 6; i++) {
data[i] = Wire.read();
}
if (crc8(data, 2) != data[2] || crc8(data + 3, 2) != data[5]) {
return false;
}
uint16_t rawTemp = (data[0] << 8) | data[1];
uint16_t rawHum = (data[3] << 8) | data[4];
temperature = -45.0 + 175.0 * rawTemp / 65535.0;
humidity = 100.0 * rawHum / 65535.0;
return true;
}
void handleRoot() {
readSHT30();
String html = "";
html += "<!DOCTYPE html><html><head>";
html += "<meta charset='UTF-8'>";
html += "<meta name='viewport' content='width=device-width, initial-scale=1'>";
html += "<meta http-equiv='refresh' content='5'>";
html += "<title>ESP8266 SHT30</title>";
html += "<style>";
html += "body{font-family:Arial;background:#f4f4f4;text-align:center;padding:30px;}";
html += ".card{background:white;padding:25px;border-radius:16px;display:inline-block;box-shadow:0 4px 16px #ccc;min-width:260px;}";
html += ".value{font-size:36px;font-weight:bold;margin:15px;}";
html += "a{display:block;margin-top:20px;color:#0366d6;text-decoration:none;}";
html += "</style>";
html += "</head><body>";
html += "<div class='card'>";
html += "<h2>ESP8266 SHT30</h2>";
if (sht30Ok) {
html += "<div>温度</div>";
html += "<div class='value'>" + String(temperature, 2) + " ℃</div>";
html += "<div>湿度</div>";
html += "<div class='value'>" + String(humidity, 2) + " %RH</div>";
} else {
html += "<h3>SHT30 读取失败</h3>";
}
html += "<p>IP: " + WiFi.localIP().toString() + "</p>";
html += "<p>每 5 秒自动刷新</p>";
html += "<a href='/json'>查看 JSON 数据</a>";
html += "<a href='/update'>网页 OTA 更新</a>";
html += "</div>";
html += "</body></html>";
server.send(200, "text/html; charset=utf-8", html);
}
void handleJson() {
readSHT30();
String json = "{";
json += "\"ok\":";
json += sht30Ok ? "true" : "false";
json += ",";
json += "\"temperature\":";
json += String(temperature, 2);
json += ",";
json += "\"humidity\":";
json += String(humidity, 2);
json += ",";
json += "\"ip\":\"";
json += WiFi.localIP().toString();
json += "\"";
json += "}";
server.send(200, "application/json; charset=utf-8", json);
}
void setup() {
Serial.begin(115200);
delay(1000);
Wire.begin(4, 5); // SDA=D2/GPIO4, SCL=D1/GPIO5
Serial.println();
Serial.println("Connecting WiFi...");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
int retry = 0;
while (WiFi.status() != WL_CONNECTED && retry < 60) {
delay(500);
Serial.print(".");
retry++;
}
Serial.println();
if (WiFi.status() == WL_CONNECTED) {
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("WiFi connect failed");
}
if (MDNS.begin("sht30")) {
Serial.println("mDNS started: http://sht30.local");
}
server.on("/", handleRoot);
server.on("/json", handleJson);
// 网页 OTA 地址:http://设备IP/update
httpUpdater.setup(&server, "/update", otaUser, otaPass);
server.begin();
Serial.println("HTTP server started");
Serial.println("Open:");
Serial.print("http://");
Serial.println(WiFi.localIP());
Serial.println("or:");
Serial.println("http://sht30.local");
Serial.println("OTA:");
Serial.print("http://");
Serial.print(WiFi.localIP());
Serial.println("/update");
}
void loop() {
sht30Ok = readSHT30();
server.handleClient();
MDNS.update();
static unsigned long lastPrint = 0;
if (millis() - lastPrint > 3000) {
lastPrint = millis();
if (sht30Ok) {
Serial.print("Temperature: ");
Serial.print(temperature, 2);
Serial.println(" °C");
Serial.print("Humidity: ");
Serial.print(humidity, 2);
Serial.println(" %RH");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
Serial.println("------------------");
} else {
Serial.println("SHT30 read failed");
}
}
}
ota升级
