<!DOCTYPE html> <html> <head> <title><CS></title> </head> <body> <h3>Please enter your question.</h3> <form action="/middle" method="post"> <textarea name="text" rows="4" cols="50"></textarea> <br> <input type="submit" value="确定"> <br> </form> </body> </html> 改为居中自适应
时间: 2023-08-14 10:53:50 浏览: 184
您可以将以下 CSS 样式添加到 `<head>` 标签中的 `<style>` 标签中,以使表单居中和自适应屏幕大小:
```html
<!DOCTYPE html>
<html>
<head>
<title><CS></title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
form {
display: flex;
flex-direction: column;
align-items: center;
}
textarea {
width: 100%;
}
</style>
</head>
<body>
<h3>Please enter your question.</h3>
<form action="/middle" method="post">
<textarea name="text" rows="4" cols="50"></textarea>
<br>
<input type="submit" value="确定">
<br>
</form>
</body>
</html>
```
这样,表单将垂直居中显示,并且文本区域的宽度将适应屏幕大小。
阅读全文
相关推荐



<!DOCTYPE HTML> <html> <head> <title>吃了么外卖网</title> <meta name="renderer" content="webkit"> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui"> <meta name="generator" content="sch" data-variable=",,10001,,," /> <meta name="description" content="网站描述,一般显示在搜索引擎搜索结果中的描述文字,用于介绍网站,吸引浏览者点击。" /> <meta name="keywords" content="" /> </head> <body class="met-navfixed"> <button type="button" class="navbar-toggle hamburger hamburger-close collapsed" data-target="#example-navbar-default-collapse" data-toggle="collapse"> Toggle navigation </button> < img src="images/348c7538a6db391afb013dd0f7a6f75.png" alt="吃了么外卖网" title="吃了么外卖网" /> 首页 美食商城 我的订单 根据这个html代码更改使表单的数据保存到PHPMyAdmin后端的数据表中,创建相应的表和连接方式


這程式碼有什麼問題嗎,想要穩穩運行溫度監控
#include <SPI.h>
#include <Ethernet.h>
#include
#include "esp_system.h"
#include "esp_mac.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include
#include <ArduinoJson.h>
#include <NeoPixelBus.h>
#include "esp_log.h"
#define MAX_SENSORS 50
OneWire* oneWireBuses[43] = {nullptr}; // 以 GPIO 編號為 index
DallasTemperature* sensors[43] = {nullptr};
String sensorROMs[MAX_SENSORS];
int sensorGPIOs[MAX_SENSORS];
int sensorCount = 0;
unsigned long lastReadTime = 0;
#define W5500_CS 10
EthernetClient ethClient;
EthernetServer server(80);
Preferences prefs;
PubSubClient mqttClient(ethClient);
unsigned long lastMQTTReconnect = 0;
byte mac[6];
char deviceName[32];
#define RESET_BUTTON_PIN 0
unsigned long buttonPressTime = 0;
bool buttonHeld = false;
#define LED_PIN 48
#define NUM_LEDS 1
NeoPixelBus<NeoGrbFeature, NeoEsp32BitBangWs2812xMethod> strip(NUM_LEDS, LED_PIN);
// MQTT 參數
String mqttHost = "";
int mqttPort = 1883;
String mqttUser = "";
String mqttPass = "";
// ==== 建立 MAC ====
void generateMac(byte* mac) {
uint8_t baseMac[6];
esp_efuse_mac_get_default(baseMac);
mac[0] = 0x02;
mac[1] = 0x00;
mac[2] = 0x00;
mac[3] = baseMac[3];
mac[4] = baseMac[4];
mac[5] = baseMac[5] + 1;
}
// ==== Ethernet 初始化 ====
bool connectEthernet(int maxRetries = 5) {
Ethernet.init(W5500_CS);
for (int i = 0; i < maxRetries; i++) {
Serial.printf("🔌 第 %d 次嘗試 DHCP...\n", i + 1);
if (Ethernet.begin(mac, 3000)) {
Serial.print("✅ Ethernet IP: ");
Serial.println(Ethernet.localIP());
return true;
}
delay(500); // 等一下再重試
}
Serial.println("⚠️ DHCP 失敗,使用手動 IP");
IPAddress ip(192, 168, 1, 222);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
Ethernet.begin(mac, ip, gateway, gateway, subnet);
return false;
}
// ==== 載入 MQTT 設定 ====
void loadMQTTConfig() {
prefs.begin("config", true);
mqttHost = prefs.getString("mqttHost", "");
mqttPort = prefs.getInt("mqttPort", 1883);
mqttUser = prefs.getString("mqttUser", "");
mqttPass = prefs.getString("mqttPass", "");
prefs.end();
}
// ==== 產生設定網頁 ====
void handleRoot(EthernetClient &client) {
prefs.begin("config", true);
int romCount = prefs.getInt("romCount", 0);
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html; charset=utf-8");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE html><html><head><meta charset='UTF-8'><title>設定頁</title>");
client.println("<style>body{font-family:sans-serif;line-height:1.5;}input{width:200px;}</style></head><body>");
client.println("MQTT 設定頁");
client.println("<form action='/save_mqtt' method='get'>");
client.printf("Host: <input name='host' value='%s'>
", mqttHost.c_str());
client.printf("Port: <input name='port' value='%d'>
", mqttPort);
client.printf("User: <input name='user' value='%s'>
", mqttUser.c_str());
client.printf("Pass: <input name='pass' value='%s'>
", mqttPass.c_str());
client.println("<input type='submit' value='儲存'></form>
");
client.println("目前設定:");
client.printf("Host: %s", mqttHost.c_str());
client.printf("Port: %d", mqttPort);
client.printf("User: %s", mqttUser.c_str());
client.printf("Pass: %s", mqttPass.c_str());
client.println("
");
client.println("新增感測器");
client.println("<form action='/add_rom' method='get'>");
client.println("ROM: <input name='rom'>
");
client.println("GPIO: <input name='gpio' type='number'>
");
client.println("<input type='submit' value='新增感測器'></form>
");
client.println("目前感測器");
for (int i = 0; i < romCount; i++) {
String rom = prefs.getString(("rom" + String(i)).c_str(), "");
int gpio = prefs.getInt(("gpio" + String(i)).c_str(), 0);
client.printf("ROM: %s @ GPIO %d 刪除", rom.c_str(), gpio, i);
}
client.println("</body></html>");
prefs.end();
}
// ==== 分析 HTTP GET 請求並處理 ====
bool processRequest(String request, EthernetClient &client) {
if (request.startsWith("GET /save_mqtt?")) {
int h1 = request.indexOf("host=") + 5;
int h2 = request.indexOf("&", h1);
mqttHost = request.substring(h1, h2);
int p1 = request.indexOf("port=") + 5;
int p2 = request.indexOf("&", p1);
mqttPort = request.substring(p1, p2).toInt();
int u1 = request.indexOf("user=") + 5;
int u2 = request.indexOf("&", u1);
mqttUser = request.substring(u1, u2);
int pw1 = request.indexOf("pass=") + 5;
int pw2 = request.indexOf(" ", pw1);
mqttPass = request.substring(pw1, pw2);
prefs.begin("config", false);
prefs.putString("mqttHost", mqttHost);
prefs.putInt("mqttPort", mqttPort);
prefs.putString("mqttUser", mqttUser);
prefs.putString("mqttPass", mqttPass);
prefs.end();
Serial.println("✅ 儲存 MQTT 設定");
// 重導向回首頁
client.println("HTTP/1.1 303 See Other");
client.println("Location: /");
client.println("Connection: close");
client.println();
return true;
}
if (request.startsWith("GET /add_rom?")) {
int r1 = request.indexOf("rom=") + 4;
int r2 = request.indexOf("&", r1);
String rom = request.substring(r1, r2);
int g1 = request.indexOf("gpio=") + 5;
int g2 = request.indexOf(" ", g1);
int gpio = request.substring(g1, g2).toInt();
prefs.begin("config", false);
int count = prefs.getInt("romCount", 0);
delay(10);
prefs.putString(("rom" + String(count)).c_str(), rom);
delay(10);
prefs.putInt(("gpio" + String(count)).c_str(), gpio);
delay(10);
prefs.putInt("romCount", count + 1);
prefs.end();
Serial.printf("✅ 新增感測器 ROM=%s GPIO=%d\n", rom.c_str(), gpio);
// 重導向回首頁
client.println("HTTP/1.1 303 See Other");
client.println("Location: /");
client.println("Connection: close");
client.println();
return true;
}
if (request.startsWith("GET /delete_rom?index=")) {
int i1 = request.indexOf("index=") + 6;
int i2 = request.indexOf(" ", i1);
int index = request.substring(i1, i2).toInt();
prefs.begin("config", false);
int count = prefs.getInt("romCount", 0);
for (int i = index; i < count - 1; i++) {
prefs.putString(("rom" + String(i)).c_str(), prefs.getString(("rom" + String(i + 1)).c_str()));
prefs.putInt(("gpio" + String(i)).c_str(), prefs.getInt(("gpio" + String(i + 1)).c_str()));
}
prefs.remove(("rom" + String(count - 1)).c_str());
prefs.remove(("gpio" + String(count - 1)).c_str());
prefs.putInt("romCount", count - 1);
prefs.end();
Serial.printf("🗑 已刪除 index %d 的感測器\n", index);
// 重導向回首頁
client.println("HTTP/1.1 303 See Other");
client.println("Location: /");
client.println("Connection: close");
client.println();
return true;
}
return false; // 表示沒有提前處理完
}
void initTemperatureSensors() {
prefs.begin("config", true);
sensorCount = prefs.getInt("romCount", 0);
for (int i = 0; i < sensorCount; i++) {
sensorROMs[i] = prefs.getString(("rom" + String(i)).c_str(), "");
sensorGPIOs[i] = prefs.getInt(("gpio" + String(i)).c_str(), 0);
int gpio = sensorGPIOs[i];
if (gpio >= 0 && gpio < 43) {
if (!oneWireBuses[gpio]) {
oneWireBuses[gpio] = new OneWire(gpio);
sensors[gpio] = new DallasTemperature(oneWireBuses[gpio]);
sensors[gpio]->begin();
delay(10); // 加一點延遲
publishDiscovery(sensorROMs[i]);
yield(); // 讓其他系統任務有機會執行
Serial.printf("✅ 初始化感測器 GPIO %d\n", gpio);
}
}
}
prefs.end();
}
void readTemperatures() {
if (millis() - lastReadTime < 1000) return;
lastReadTime = millis();
// 先 request 每個 GPIO 上的所有感測器(不重複)
bool requested[43] = { false };
for (int i = 0; i < sensorCount; i++) {
int gpio = sensorGPIOs[i];
// 🛡 檢查 sensors[gpio] 是否有效
if (gpio < 0 || gpio >= 43 || sensors[gpio] == nullptr) continue;
if (!requested[gpio]) {
sensors[gpio]->requestTemperatures();
requested[gpio] = true;
}
}
// 再逐支感測器取值
for (int i = 0; i < sensorCount; i++) {
int gpio = sensorGPIOs[i];
String romStr = sensorROMs[i];
// 🛡 安全檢查
if (gpio < 0 || gpio >= 43 || sensors[gpio] == nullptr) continue;
if (romStr.length() != 16) continue;
DeviceAddress addr;
for (int b = 0; b < 8; b++) {
char buf[3] = { romStr[b * 2], romStr[b * 2 + 1], 0 };
addr[b] = strtoul(buf, nullptr, 16);
}
float tempC = sensors[gpio]->getTempC(addr);
if (tempC != DEVICE_DISCONNECTED_C) {
if (mqttClient.connected()) {
String topic = "home/" + String(deviceName) + "/temperature/" + romStr;
String payload = String(tempC, 1);
mqttClient.publish(topic.c_str(), payload.c_str());
}
Serial.printf("🌡 感測器 %s @ GPIO %d = %.1f°C\n", romStr.c_str(), gpio, tempC);
} else {
Serial.printf("⚠️ 無法讀取感測器 %s @ GPIO %d\n", romStr.c_str(), gpio);
if (mqttClient.connected()) {
String topic = "home/" + String(deviceName) + "/temperature/" + romStr;
mqttClient.publish(topic.c_str(), "null");
}
}
}
}
void reconnectMQTT() {
if (mqttHost == "") return;
if (!mqttClient.connected()) {
Serial.print("🔌 嘗試連線 MQTT...");
String willTopic = "home/" + String(deviceName) + "/status";
String willPayload = "offline";
if (mqttClient.connect(deviceName, mqttUser.c_str(), mqttPass.c_str(),
willTopic.c_str(), 1, true, willPayload.c_str())) {
Serial.println("✅ MQTT 已連線");
// ✅ MQTT 連線成功,改成綠燈
RgbColor green(0, 5, 0); // 低亮度綠燈
strip.SetPixelColor(0, green);
strip.Show();
String onlineTopic = "home/" + String(deviceName) + "/status";
mqttClient.publish(onlineTopic.c_str(), "online", true);
// ✅ 重新發送 Home Assistant discovery 資訊
for (int i = 0; i < sensorCount; i++) {
publishDiscovery(sensorROMs[i]);
delay(100);
}
} else {
Serial.printf("❌ 連線失敗,代碼: %d\n", mqttClient.state());
RgbColor red(5, 0, 0); // 低亮度紅燈
strip.SetPixelColor(0, red);
strip.Show();
}
}
}
// 🛠 模擬重啟 W5500 的函式
void resetEthernet() {
SPI.end();
delay(100);
SPI.begin(36, 37, 35, W5500_CS);
Ethernet.init(W5500_CS);
}
void publishDiscovery(const String& rom) {
String topic = "homeassistant/sensor/" + rom + "/config";
String payload = "{";
payload += "\"name\":\"DS18B20 " + rom + "\",";
payload += "\"stat_t\":\"home/" + String(deviceName) + "/temperature/" + rom + "\",";
payload += "\"unit_of_meas\":\"°C\",";
payload += "\"dev_cla\":\"temperature\",";
payload += "\"val_tpl\":\"{{ value }}\",";
payload += "\"uniq_id\":\"ds18b20_" + rom + "\"";
payload += "}";
mqttClient.publish(topic.c_str(), payload.c_str(), true);
}
void initRGB() {
strip.Begin();
strip.Show(); // 清除顏色
RgbColor yellow(10, 10, 0); // 黃色代表初始化中
strip.SetPixelColor(0, yellow);
strip.Show();
}
// ==== 初始化 ====
void setup() {
delay(2000);
Serial.begin(115200);
yield();
delay(100);
esp_log_level_set("*", ESP_LOG_VERBOSE);
yield();
delay(500);
pinMode(RESET_BUTTON_PIN, INPUT_PULLUP);
yield();
delay(100);
initRGB();
yield();
delay(100);
esp_reset_reason_t reason = esp_reset_reason();
Serial.printf("🔁 上次重啟原因:%d\n", reason);
yield();
delay(100);
generateMac(mac);
sprintf(deviceName, "esp32_s3_%02X%02X%02X", mac[3], mac[4], mac[5]);
Serial.printf("📛 裝置名稱:%s\n", deviceName);
yield();
delay(100);
delay(2000);
SPI.begin(36, 37, 35, W5500_CS);
Ethernet.init(W5500_CS);
yield();
delay(100);
connectEthernet(); // DHCP 最多 5 次,每次最多 3 秒內完成
yield();
delay(100);
loadMQTTConfig();
yield();
delay(100);
// initTemperatureSensors(); // 感測器多的話可能吃時間
yield();
delay(100);
server.begin();
Serial.println("🌐 Web Server 啟動完成");
yield();
delay(100);
if (mqttHost.length() > 0) {
mqttClient.setServer(mqttHost.c_str(), mqttPort);
}
delay(500); // 再等一下,確保系統穩定
}
bool lastLinkUp = true;
bool usingStaticIP = false;
bool sensorsInitialized = false;
// ==== 主迴圈 ====
void loop() {
if (digitalRead(RESET_BUTTON_PIN) == LOW) {
if (!buttonHeld) {
buttonHeld = true;
buttonPressTime = millis();
} else if (millis() - buttonPressTime > 5000) {
Serial.println("🧹 長按按鍵超過 5 秒,清除所有設定並重啟");
prefs.begin("config", false);
prefs.clear();
prefs.end();
delay(1000);
ESP.restart();
}
} else {
buttonHeld = false;
}
bool linkNow = Ethernet.linkStatus() == LinkON;
if (!lastLinkUp && linkNow) {
Serial.println("🔄 網路重新連線,重新初始化 Ethernet 模組");
resetEthernet();
if (Ethernet.begin(mac, 5000)) {
usingStaticIP = false;
Serial.print("✅ DHCP 成功恢復 IP: ");
Serial.println(Ethernet.localIP());
mqttClient.setServer(mqttHost.c_str(), mqttPort); // ✅ 加這行
} else {
Serial.println("⚠️ DHCP 還是失敗,使用手動 IP");
IPAddress ip(192, 168, 1, 222);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
Ethernet.begin(mac, ip, gateway, gateway, subnet);
usingStaticIP = true;
}
server.begin(); // 重啟 Web Server
}
lastLinkUp = linkNow;
EthernetClient client = server.available();
if (client) {
Serial.println("💻 來自用戶端的連線");
String request = "";
unsigned long timeout = millis() + 1000;
while (client.connected() && millis() < timeout) {
if (client.available()) {
char c = client.read();
request += c;
if (c == '\n') break;
}
}
if (!processRequest(request, client)) {
handleRoot(client);
}
client.stop();
}
static bool sensorsInitialized = false;
if (!sensorsInitialized && millis() > 3000) {
initTemperatureSensors();
sensorsInitialized = true;
}
readTemperatures();
mqttClient.loop();
if (!mqttClient.connected() && millis() - lastMQTTReconnect > 5000) {
reconnectMQTT();
lastMQTTReconnect = millis();
}
yield();
} // <--- 這個結尾大括號絕對不能漏!











