TP3.2.x判断手机端访问并设置默认访问模块的方法

手机端适配ThinkPHP
本文介绍如何在ThinkPHP框架中实现手机端自动调用Wap模块,通过判断用户代理来区分手机和桌面访问,从而提供不同的页面布局。

然后在入口文件 index.php 中加入手机端判断方法(建议放到最下面):手机端访问时调用Wap手机模块,实现在手机端访问时展示出手机网站,无需跳转域名
首先我们在./Application/Common/Conf/ 目录下建立两个公共配置文件:config.php 和config_wap.php

config.php 中:

return array(
    'DEFAULT_MODULE'=>'Home',
)

config_wap.php 中:

return array(
	'DEFAULT_MODULE'=>'Mobile',
)

然后,我们开始用关键的APP_STATUS来调用不同的模块:
在index.php文件中的21行后面也就是“定义应用目录”结束后,加入代码:

if(ismobile()){
    define('APP_STATUS','config_wap');
}else{
    define('APP_STATUS','Index');
}

然后在入口文件 index.php 中加入手机端判断方法(建议放到最下面): 

function is_mobile_request(){
    $_SERVER['ALL_HTTP'] = isset($_SERVER['ALL_HTTP']) ? $_SERVER['ALL_HTTP'] : '';
    $mobile_browser = '0';
    if(preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone|iphone|ipad|ipod|android|xoom)/i', strtolower($_SERVER['HTTP_USER_AGENT'])))
        $mobile_browser++;
    if((isset($_SERVER['HTTP_ACCEPT'])) and (strpos(strtolower($_SERVER['HTTP_ACCEPT']),'application/vnd.wap.xhtml+xml') !== false))
        $mobile_browser++;
    if(isset($_SERVER['HTTP_X_WAP_PROFILE']))
        $mobile_browser++;
    if(isset($_SERVER['HTTP_PROFILE']))
        $mobile_browser++;
        $mobile_ua = strtolower(substr($_SERVER['HTTP_USER_AGENT'],0,4));
        $mobile_agents = array(
            'w3c ','acs-','alav','alca','amoi','audi','avan','benq','bird','blac',
            'blaz','brew','cell','cldc','cmd-','dang','doco','eric','hipt','inno',
            'ipaq','java','jigs','kddi','keji','leno','lg-c','lg-d','lg-g','lge-',
            'maui','maxo','midp','mits','mmef','mobi','mot-','moto','mwbp','nec-',
            'newt','noki','oper','palm','pana','pant','phil','play','port','prox',
            'qwap','sage','sams','sany','sch-','sec-','send','seri','sgh-','shar',
            'sie-','siem','smal','smar','sony','sph-','symb','t-mo','teli','tim-',
            'tosh','tsm-','upg1','upsi','vk-v','voda','wap-','wapa','wapi','wapp',
            'wapr','webc','winw','winw','xda','xda-'
        );
     if(in_array($mobile_ua, $mobile_agents))
          $mobile_browser++;
     if(strpos(strtolower($_SERVER['ALL_HTTP']), 'operamini') !== false)
          $mobile_browser++;
     // Pre-final check to reset everything if the user is on Windows  
     if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows') !== false)
          $mobile_browser=0;
     // But WP7 is also Windows, with a slightly different characteristic  
     if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows phone') !== false)
          $mobile_browser++;
     if($mobile_browser>0)  
          return true;
     else
          return false;
}

参考:http://www.thinkphp.cn/code/3516.html

现在要求用arduino mega 2560主板,NodeMCU ESP-32S只作wifi模块,光敏电阻5506,声音传感器,人体电磁波传感器SR602,欧姆龙G6S-2-5VDC继电器,开关(黑色、红色、绿色、蓝色),LED,电阻,3个太阳能板5V200mA,升压模块RT9266,充电过流保护模块TP4056,一个18650锂电池3.7V2600mA,电池盒等零件,实现以下效果:共有6条线路,其中0、2、4线路链接有3个光敏、1个声音,1、3、5线路链接有3个光敏、1个人体,(同一线路的3个光敏电阻联接入一个端口,另一个传感器接入另一个端口),可以切换3种传感器感应模式(光线/声音/人体,每次只有一种传感器工作),3种颜色不同的LED模式指示灯在对应时刻亮起,当感知到6条线路中某条线路有最大的光线/声音/电磁波,控制继电器打开,对那条线路施加较大电流,其余线路中无较大电流(持续时间到:此线路的信号减弱至小于另一条线路中传来的信号,则关闭此条线路的继电器,打开信号更强的那个传感器)。如果同时有多个线路感受到了信号,则控制其中信号最大的线路的继电器打开。三个模式设计为后按下的模式覆盖前一个模式。老师说这个欧姆龙继电器连接到电路里不用加二极管和三极管,也不会损伤电路,而且线圈段的两个接口一个接GND,一个接D 。3个太阳能电路板同时给下面的电池供电,不管出于什么模式。现在加入NodeMCU-32S仅仅作为wifi模块,使装置可以在手机和电脑查看所有传感器的实时数据(6个光照强度、3个声音强度、3个人体感应状态),在网页上远程切换三种传感器模式(光敏/声音/人体),同时实际电路里对应LED亮起,根据太阳能电池电量自动切换节能模式,WiFi模块监控电池电压,节能模式为电量低(40%电量)时禁用高耗电功能(如降低采样频率)。提供现有的完整代码,目前的问题是网页上数据显示都为0,模式切换时电路中的LED也没有变化,请改正代码至可实现上述功能。arduino mega:#include <SoftwareSerial.h> // 引脚定义 const int lightPins[6] = {A0, A2, A3, A5, A6, A8}; const int soundPins[3] = {A1, A4, A7}; const int pirPins[3] = {2, 3, 4}; const int relayPins[6] = {22, 23, 24, 25, 26, 27}; const int modeLEDs[3] = {28, 29, 30}; // 绿,蓝,红 const int modeButtons[3] = {31, 32, 33}; // 系统变量 volatile char currentMode = &#39;L&#39;; // L:光 S:声 P:人体 volatile int lastActiveRelay = -1; unsigned long lastSample = 0; const int sampleInterval = 200; // ms // 按钮状态变量 volatile bool buttonPressed[3] = {false, false, false}; volatile unsigned long lastDebounceTime[3] = {0, 0, 0}; const int debounceDelay = 50; void setup() { Serial.begin(115200); Serial1.begin(9600); // 与ESP32通信 // 初始化继电器 for(int i=0; i<6; i++) { pinMode(relayPins[i], OUTPUT); digitalWrite(relayPins[i], LOW); } // 初始化传感器 for(int i=0; i<3; i++) { pinMode(pirPins[i], INPUT); } // 初始化LED和按钮 for(int i=0; i<3; i++) { pinMode(modeLEDs[i], OUTPUT); pinMode(modeButtons[i], INPUT_PULLUP); digitalWrite(modeLEDs[i], LOW); } digitalWrite(modeLEDs[0], HIGH); // 默认光模式 Serial.println("System Initialized - Fixed Version"); // 添加中断以提高按钮响应 attachInterrupt(digitalPinToInterrupt(modeButtons[0]), button0Pressed, FALLING); attachInterrupt(digitalPinToInterrupt(modeButtons[1]), button1Pressed, FALLING); attachInterrupt(digitalPinToInterrupt(modeButtons[2]), button2Pressed, FALLING); } // 中断服务函数 void button0Pressed() { if ((millis() - lastDebounceTime[0]) > debounceDelay) { buttonPressed[0] = true; lastDebounceTime[0] = millis(); } } void button1Pressed() { if ((millis() - lastDebounceTime[1]) > debounceDelay) { buttonPressed[1] = true; lastDebounceTime[1] = millis(); } } void button2Pressed() { if ((millis() - lastDebounceTime[2]) > debounceDelay) { buttonPressed[2] = true; lastDebounceTime[2] = millis(); } } void loop() { // 检查按钮中断 if (buttonPressed[0]) { changeMode(0); buttonPressed[0] = false; } if (buttonPressed[1]) { changeMode(1); buttonPressed[1] = false; } if (buttonPressed[2]) { changeMode(2); buttonPressed[2] = false; } // 定时采样 if(millis() - lastSample > sampleInterval) { lastSample = millis(); // 读取所有传感器 int lightValues[6]; int soundValues[3]; int pirValues[3]; for(int i=0; i<6; i++) lightValues[i] = analogRead(lightPins[i]); for(int i=0; i<3; i++) soundValues[i] = analogRead(soundPins[i]); for(int i=0; i<3; i++) pirValues[i] = digitalRead(pirPins[i]); // 控制继电器 controlRelays(lightValues, soundValues, pirValues); // 发送数据到ESP32 sendSensorData(lightValues, soundValues, pirValues); // 调试输出 Serial.print("Mode: "); Serial.print(currentMode); Serial.print(" | Light: "); for(int i=0; i<6; i++) { Serial.print(lightValues[i]); Serial.print(" "); } Serial.print(" | Sound: "); for(int i=0; i<3; i++) { Serial.print(soundValues[i]); Serial.print(" "); } Serial.print(" | PIR: "); for(int i=0; i<3; i++) { Serial.print(pirValues[i]); Serial.print(" "); } Serial.print(" | Active Relay: "); Serial.println(lastActiveRelay); } // 处理来自ESP32的命令 handleSerialCommands(); } void changeMode(int modeIndex) { // 关闭所有LED for(int i=0; i<3; i++) digitalWrite(modeLEDs[i], LOW); // 设置新LED digitalWrite(modeLEDs[modeIndex], HIGH); // 更新模式 switch(modeIndex) { case 0: currentMode = &#39;L&#39;; break; case 1: currentMode = &#39;S&#39;; break; case 2: currentMode = &#39;P&#39;; break; } // 关闭所有继电器 resetRelays(); Serial.print("Mode changed to: "); Serial.println(currentMode); // 立即发送模式更新 Serial1.print("!MODE:"); Serial1.println(currentMode); } void resetRelays() { for(int i=0; i<6; i++) digitalWrite(relayPins[i], LOW); lastActiveRelay = -1; } void controlRelays(int lights[], int sounds[], int pirs[]) { int maxValue = 0; int activeRelay = -1; switch(currentMode) { case &#39;L&#39;: // 光模式 for(int i=0; i<6; i++) { if(lights[i] > maxValue && lights[i] > 300) { maxValue = lights[i]; activeRelay = i; } } break; case &#39;S&#39;: // 声音模式 for(int i=0; i<3; i++) { int idx = i*2; // 对应线路0,2,4 if(sounds[i] > maxValue && sounds[i] > 500) { maxValue = sounds[i]; activeRelay = idx; } } break; case &#39;P&#39;: // 人体模式 for(int i=0; i<3; i++) { if(pirs[i] == HIGH) { activeRelay = i*2 + 1; // 对应线路1,3,5 break; // 优先第一个检测到的 } } break; } // 更新继电器状态 if(activeRelay != lastActiveRelay) { resetRelays(); if(activeRelay != -1) { digitalWrite(relayPins[activeRelay], HIGH); lastActiveRelay = activeRelay; Serial.print("Activated relay: "); Serial.println(activeRelay); } } } void sendSensorData(int lights[], int sounds[], int pirs[]) { // 格式: $L0,L1,L2,L3,L4,L5,S0,S1,S2,P0,P1,P2,M\n Serial1.print(&#39;$&#39;); for(int i=0; i<6; i++) { Serial1.print(lights[i]); Serial1.print(&#39;,&#39;); } for(int i=0; i<3; i++) { Serial1.print(sounds[i]); Serial1.print(&#39;,&#39;); } for(int i=0; i<3; i++) { Serial1.print(pirs[i]); if(i<2) Serial1.print(&#39;,&#39;); } Serial1.print(&#39;,&#39;); Serial1.print(currentMode); Serial1.println(); } void handleSerialCommands() { while(Serial1.available()) { char cmd = Serial1.read(); Serial.print("Received command from ESP32: "); Serial.println(cmd); switch(cmd) { case &#39;L&#39;: changeMode(0); break; case &#39;S&#39;: changeMode(1); break; case &#39;P&#39;: changeMode(2); break; } } }esp32:#include <WiFi.h> #include <WebServer.h> const char* ssid = "iQOO 11"; const char* password = "wdf25892"; WebServer server(80); const int batteryPin = 36; // VP引脚 // 传感器数据存储 int lightValues[6] = {0}; int soundValues[3] = {0}; int pirValues[3] = {0}; char currentMode = &#39;L&#39;; float batteryVoltage = 0.0; bool powerSaving = false; String wifiStatus = "Disconnected"; // 串口缓冲区 String serialBuffer = ""; void setup() { Serial.begin(115200); Serial1.begin(9600, SERIAL_8N1, 3, 1); // RX=3, TX=1 // 连接WiFi WiFi.begin(ssid, password); Serial.print("Connecting to WiFi"); int attempts = 0; while (WiFi.status() != WL_CONNECTED && attempts < 20) { delay(500); Serial.print("."); attempts++; } if (WiFi.status() == WL_CONNECTED) { wifiStatus = "Connected to " + String(ssid); Serial.println("\nConnected! IP: " + WiFi.localIP().toString()); } else { wifiStatus = "Failed to connect"; Serial.println("\nFailed to connect to WiFi"); WiFi.softAP("SensorHub", "12345678"); Serial.println("AP created: SensorHub, IP: " + WiFi.softAPIP().toString()); } // 设置Web服务器 server.on("/", handleRoot); server.on("/data", handleData); server.on("/setmode", handleSetMode); server.on("/debug", handleDebug); server.begin(); // 配置ADC analogReadResolution(12); analogSetAttenuation(ADC_11db); Serial.println("HTTP server started - Fixed Version"); } void loop() { server.handleClient(); // 读取电池电压 int adcValue = analogRead(batteryPin); batteryVoltage = (adcValue * 3.3 / 4095.0) * (100+220)/100.0; // 节能模式检测 (假设4.2V满电,3.2V为40%) float batteryPct = constrain((batteryVoltage - 3.2) / (4.2 - 3.2) * 100, 0, 100); bool newPowerSaving = (batteryPct < 40.0); if(newPowerSaving != powerSaving) { powerSaving = newPowerSaving; Serial.println(powerSaving ? "Enter Power Saving" : "Exit Power Saving"); } // 处理串口数据 while(Serial1.available()) { char c = Serial1.read(); // 处理特殊命令 if(c == &#39;!&#39;) { String command = Serial1.readStringUntil(&#39;\n&#39;); command.trim(); if(command.startsWith("MODE:")) { currentMode = command.charAt(5); Serial.println("Received mode update: " + String(currentMode)); } continue; } // 处理传感器数据 serialBuffer += c; if(c == &#39;\n&#39;) { if(serialBuffer.startsWith("$")) { Serial.println("Received data: " + serialBuffer); parseSensorData(serialBuffer); } serialBuffer = ""; } } delay(powerSaving ? 1000 : 200); } void parseSensorData(String data) { // 移除起始符和换行符 data.replace("$", ""); data.trim(); // 分割字符串 int values[12] = {0}; // 存储12个传感器值 int index = 0; int startPos = 0; char newMode = currentMode; // 保存解析出的新模式 for(int i=0; i<=data.length(); i++) { if(i == data.length() || data.charAt(i) == &#39;,&#39;) { String numStr; if(i == data.length()) { numStr = data.substring(startPos); } else { numStr = data.substring(startPos, i); } startPos = i+1; if(numStr.length() > 0) { // 处理模式字符(最后一个值) if(index == 12) { if(numStr.length() == 1) { newMode = numStr.charAt(0); } } // 处理传感器数值 else if(index < 12) { values[index] = numStr.toInt(); } index++; } } } // 更新传感器数据 if(index >= 12) { for(int i=0; i<6; i++) lightValues[i] = values[i]; for(int i=0; i<3; i++) soundValues[i] = values[6+i]; for(int i=0; i<3; i++) pirValues[i] = values[9+i]; currentMode = newMode; // 更新模式 Serial.println("Updated sensor data. Mode: " + String(currentMode)); } } // 其他函数保持不变(handleRoot, handleData, handleSetMode, handleDebug) // ... 保持原有的HTML和handle函数不变 ... void handleRoot() { String html = R"=====( <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Smart Sensor Hub</title> <style> body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; } .card { border: 1px solid #ddd; border-radius: 8px; padding: 15px; margin-bottom: 20px; } .sensor-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; } .sensor-item { padding: 10px; background: #f9f9f9; border-radius: 4px; text-align: center; } .status { font-weight: bold; } .online { color: green; } .offline { color: red; } .active { background-color: #4CAF50; color: white; } button { padding: 10px 15px; margin: 5px; font-size: 16px; cursor: pointer; } .led { display: inline-block; width: 20px; height: 20px; border-radius: 50%; margin-right: 10px; background-color: #ccc; } .led.active { background-color: #4CAF50; } </style> <script> let currentMode = &#39;L&#39;; function updateData() { fetch(&#39;/data&#39;) .then(response => { if(!response.ok) throw new Error(&#39;Network error&#39;); return response.json(); }) .then(data => { // 更新模式 currentMode = data.mode; document.getElementById(&#39;mode&#39;).textContent = getModeName(currentMode); // 更新LED指示灯 document.querySelectorAll(&#39;.led&#39;).forEach(led => { led.classList.remove(&#39;active&#39;); }); document.getElementById(`led${currentMode}`).classList.add(&#39;active&#39;); // 更新传感器数据 for(let i=0; i<6; i++) { document.getElementById(&#39;light&#39;+i).textContent = data.light[i]; } for(let i=0; i<3; i++) { document.getElementById(&#39;sound&#39;+i).textContent = data.sound[i]; } for(let i=0; i<3; i++) { document.getElementById(&#39;pir&#39;+i).textContent = data.pir[i] ? "Detected" : "None"; document.getElementById(&#39;pir&#39;+i).className = data.pir[i] ? &#39;sensor-item active&#39; : &#39;sensor-item&#39;; } // 更新电池状态 document.getElementById(&#39;battery&#39;).textContent = data.battery.toFixed(2) + "V (" + data.batteryPct + "%)"; // 更新WiFi状态 document.getElementById(&#39;wifiStatus&#39;).textContent = data.wifiStatus; document.getElementById(&#39;wifiStatus&#39;).className = data.wifiStatus.includes(&#39;Connected&#39;) ? &#39;status online&#39; : &#39;status offline&#39;; setTimeout(updateData, 1000); }) .catch(error => { console.error(&#39;Error:&#39;, error); document.getElementById(&#39;status&#39;).textContent = &#39;Connection Error - Retrying...&#39;; setTimeout(updateData, 3000); }); } function getModeName(modeChar) { switch(modeChar) { case &#39;L&#39;: return &#39;Light Mode&#39;; case &#39;S&#39;: return &#39;Sound Mode&#39;; case &#39;P&#39;: return &#39;PIR Mode&#39;; default: return &#39;Unknown&#39;; } } function setMode(mode) { fetch(&#39;/setmode?m=&#39; + mode) .then(response => { if(response.ok) { document.getElementById(&#39;modeStatus&#39;).textContent = &#39;Mode changed successfully!&#39;; setTimeout(() => document.getElementById(&#39;modeStatus&#39;).textContent = &#39;&#39;, 2000); } else { document.getElementById(&#39;modeStatus&#39;).textContent = &#39;Failed to change mode&#39;; } }); } document.addEventListener(&#39;DOMContentLoaded&#39;, function() { updateData(); }); </script> </head> <body> <div class="card"> <h1>Smart Sensor Hub <span class="led" id="ledL"></span><span class="led" id="ledS"></span><span class="led" id="ledP"></span></h1> <div id="status">System Status: <span id="wifiStatus" class="status">Loading...</span></div> </div> <div class="card"> <h2>Power Status</h2> <p>Battery: <span id="battery">--</span></p> <p>Current Mode: <span id="mode">--</span></p> <p id="modeStatus" style="color:green;"></p> </div> <div class="card"> <h2>Control Panel</h2> <button onclick="setMode(&#39;L&#39;)">Light Mode</button> <button onclick="setMode(&#39;S&#39;)">Sound Mode</button> <button onclick="setMode(&#39;P&#39;)">PIR Mode</button> </div> <div class="card"> <h2>Light Sensors</h2> <div class="sensor-grid"> <div class="sensor-item">Line 0: <span id="light0">--</span></div> <div class="sensor-item">Line 1: <span id="light1">--</span></div> <div class="sensor-item">Line 2: <span id="light2">--</span></div> <div class="sensor-item">Line 3: <span id="light3">--</span></div> <div class="sensor-item">Line 4: <span id="light4">--</span></div> <div class="sensor-item">Line 5: <span id="light5">--</span></div> </div> </div> <div class="card"> <h2>Sound Sensors</h2> <div class="sensor-grid"> <div class="sensor-item">Line 0: <span id="sound0">--</span></div> <div class="sensor-item">Line 2: <span id="sound1">--</span></div> <div class="sensor-item">Line 4: <span id="sound2">--</span></div> </div> </div> <div class="card"> <h2>PIR Sensors</h2> <div class="sensor-grid"> <div class="sensor-item">Line 1: <span id="pir0">--</span></div> <div class="sensor-item">Line 3: <span id="pir1">--</span></div> <div class="sensor-item">Line 5: <span id="pir2">--</span></div> </div> </div> <div class="card"> <p><a href="/debug">Debug Information</a></p> </div> </body> </html> )====="; server.send(200, "text/html", html); } void handleData() { String json = "{"; json += "\"light\":[" + String(lightValues[0]); for(int i=1; i<6; i++) json += "," + String(lightValues[i]); json += "],\"sound\":[" + String(soundValues[0]); for(int i=1; i<3; i++) json += "," + String(soundValues[i]); json += "],\"pir\":[" + String(pirValues[0]); for(int i=1; i<3; i++) json += "," + String(pirValues[i]); float batteryPct = constrain((batteryVoltage - 3.2) / (4.2 - 3.2) * 100, 0, 100); json += "],\"battery\":" + String(batteryVoltage, 2); json += ",\"batteryPct\":" + String(batteryPct, 1); json += ",\"mode\":\"" + String(currentMode) + "\""; json += ",\"wifiStatus\":\"" + wifiStatus + "\"}"; server.send(200, "application/json", json); } void handleSetMode() { if(server.hasArg("m")) { char mode = server.arg("m")[0]; Serial1.write(mode); // 转发到Arduino server.send(200, "text/plain", "Mode changed"); // 立即更新当前模式 currentMode = mode; Serial.println("Set mode via web: " + String(mode)); } else { server.send(400, "text/plain", "Invalid request"); } } void handleDebug() { String debug = "=== System Debug ===\n\n"; debug += "WiFi Status: " + wifiStatus + "\n"; debug += "Battery Voltage: " + String(batteryVoltage, 2) + "V\n"; debug += "Power Saving: " + String(powerSaving ? "ON" : "OFF") + "\n"; debug += "Current Mode: " + String(currentMode) + "\n\n"; debug += "Light Values:\n"; for(int i=0; i<6; i++) debug += " L" + String(i) + ": " + String(lightValues[i]) + "\n"; debug += "\nSound Values:\n"; for(int i=0; i<3; i++) debug += " S" + String(i) + ": " + String(soundValues[i]) + "\n"; debug += "\nPIR Values:\n"; for(int i=0; i<3; i++) debug += " P" + String(i) + ": " + String(pirValues[i]) + "\n"; debug += "\nSerial Buffer: " + serialBuffer + "\n"; server.send(200, "text/plain", debug); }
最新发布
07-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值