smart-home/smart-home-app/utils/mobileHttpDebug.js
2026-02-26 09:16:34 +08:00

422 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 移动端HTTP调试工具
* 专门用于调试uni-app在移动设备上的HTTP请求问题
*/
/**
* 详细的HTTP请求调试
*/
export async function debugHTTPRequest(url, options = {}) {
console.log('🔧 开始HTTP请求调试...')
console.log('=' * 60)
const debugInfo = {
url,
options,
environment: {},
networkInfo: {},
requestDetails: {},
response: null,
error: null,
recommendations: []
}
try {
// 1. 收集环境信息
console.log('📱 收集环境信息...')
debugInfo.environment = await collectEnvironmentInfo()
// 2. 检查网络状态
console.log('📶 检查网络状态...')
debugInfo.networkInfo = await collectNetworkInfo()
// 3. 分析请求配置
console.log('⚙️ 分析请求配置...')
debugInfo.requestDetails = analyzeRequestConfig(url, options)
// 4. 执行HTTP请求
console.log('🌐 执行HTTP请求...')
const result = await executeDebugRequest(url, options)
if (result.success) {
debugInfo.response = result.response
console.log('✅ HTTP请求成功')
} else {
debugInfo.error = result.error
console.log('❌ HTTP请求失败')
}
// 5. 生成诊断建议
debugInfo.recommendations = generateRecommendations(debugInfo)
} catch (error) {
console.error('❌ HTTP调试异常:', error)
debugInfo.error = error
}
// 输出调试报告
printDebugReport(debugInfo)
return debugInfo
}
/**
* 收集环境信息
*/
async function collectEnvironmentInfo() {
const env = {}
try {
// 系统信息
const systemInfo = uni.getSystemInfoSync()
env.platform = systemInfo.platform
env.system = systemInfo.system
env.version = systemInfo.version
env.SDKVersion = systemInfo.SDKVersion
env.brand = systemInfo.brand
env.model = systemInfo.model
console.log(`📱 设备: ${env.brand} ${env.model}`)
console.log(`💻 系统: ${env.system}`)
console.log(`🔢 版本: ${env.version}`)
} catch (error) {
console.log('⚠️ 无法获取系统信息:', error)
}
return env
}
/**
* 收集网络信息
*/
async function collectNetworkInfo() {
const network = {}
try {
// 网络类型
const networkType = await uni.getNetworkType()
network.type = networkType.networkType
network.isConnected = networkType.isConnected
console.log(`📶 网络类型: ${network.type}`)
console.log(`🔗 连接状态: ${network.isConnected ? '已连接' : '未连接'}`)
// 如果uni.getNetworkType()返回未连接但类型是wifi可能是API问题
if (network.type === 'wifi' && !network.isConnected) {
console.log('⚠️ 网络状态检测可能不准确WiFi类型但显示未连接')
// 尝试简单的网络测试来验证实际连接状态
try {
const testResult = await new Promise((resolve, reject) => {
uni.request({
url: 'https://www.baidu.com',
method: 'GET',
timeout: 3000,
success: () => resolve(true),
fail: () => resolve(false)
})
})
network.actuallyConnected = testResult
console.log(`🌐 实际网络连接测试: ${testResult ? '成功' : '失败'}`)
} catch (error) {
network.actuallyConnected = false
}
}
// WiFi信息如果可用
if (network.type === 'wifi') {
try {
const wifiInfo = await uni.getConnectedWifi()
network.wifi = {
SSID: wifiInfo.SSID,
BSSID: wifiInfo.BSSID,
secure: wifiInfo.secure,
signalStrength: wifiInfo.signalStrength
}
console.log(`📡 WiFi SSID: ${network.wifi.SSID}`)
console.log(`📶 信号强度: ${network.wifi.signalStrength}`)
} catch (error) {
console.log('⚠️ 无法获取WiFi详细信息:', error?.errMsg || error || 'Permission denied')
network.wifiError = error?.errMsg || error || 'Permission denied'
// 提供权限申请建议
console.log('💡 可能需要申请位置权限才能获取WiFi信息')
}
}
} catch (error) {
console.log('❌ 网络信息获取失败:', error)
network.error = error
}
return network
}
/**
* 分析请求配置
*/
function analyzeRequestConfig(url, options) {
const analysis = {
url,
method: options.method || 'GET',
timeout: options.timeout || 60000,
headers: options.header || {},
isLocalNetwork: false,
isHTTPS: false,
issues: []
}
// URL分析
if (url.startsWith('https://')) {
analysis.isHTTPS = true
}
// 检查是否为局域网地址
const localNetworkPatterns = [
/^https?:\/\/192\.168\./,
/^https?:\/\/10\./,
/^https?:\/\/172\.(1[6-9]|2[0-9]|3[01])\./,
/^https?:\/\/localhost/,
/^https?:\/\/127\.0\.0\.1/
]
analysis.isLocalNetwork = localNetworkPatterns.some(pattern => pattern.test(url))
// 配置问题检查
if (analysis.isLocalNetwork && analysis.isHTTPS) {
analysis.issues.push('⚠️ 局域网地址使用HTTPS可能导致证书错误')
}
if (analysis.timeout < 5000) {
analysis.issues.push('⚠️ 超时时间过短建议设置为10秒以上')
}
if (!analysis.headers['User-Agent']) {
analysis.issues.push('💡 建议添加User-Agent头')
}
console.log(`🎯 请求URL: ${analysis.url}`)
console.log(`📋 请求方法: ${analysis.method}`)
console.log(`⏱️ 超时时间: ${analysis.timeout}ms`)
console.log(`🏠 局域网请求: ${analysis.isLocalNetwork ? '是' : '否'}`)
return analysis
}
/**
* 执行调试请求
*/
async function executeDebugRequest(url, options = {}) {
const startTime = Date.now()
// 构建完整的请求配置
const requestConfig = {
url,
method: options.method || 'GET',
timeout: options.timeout || 15000, // 延长到15秒
header: {
'Content-Type': 'application/json',
'User-Agent': 'uni-app/ESP32Client-Debug',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
...options.header
},
sslVerify: false,
withCredentials: false,
...options
}
console.log('📋 完整请求配置:', JSON.stringify(requestConfig, null, 2))
// 重试机制最多重试2次
for (let attempt = 1; attempt <= 2; attempt++) {
try {
console.log(`🔄 第${attempt}次尝试...`)
const response = await new Promise((resolve, reject) => {
uni.request({
...requestConfig,
success: (res) => {
const duration = Date.now() - startTime
console.log(`✅ 请求成功 (${duration}ms, 第${attempt}次尝试)`)
console.log('📄 响应状态:', res.statusCode)
console.log('📄 响应头:', res.header)
console.log('📄 响应数据:', res.data)
resolve(res)
},
fail: (err) => {
const duration = Date.now() - startTime
console.log(`❌ 请求失败 (${duration}ms, 第${attempt}次尝试)`)
console.log('❌ 错误信息:', err.errMsg)
console.log('❌ 错误码:', err.errno)
reject(err)
}
})
})
return {
success: true,
response,
duration: Date.now() - startTime,
attempts: attempt
}
} catch (error) {
if (attempt === 2) {
// 最后一次重试失败
return {
success: false,
error,
duration: Date.now() - startTime,
attempts: attempt
}
}
// 重试前等待500ms
console.log(`⏳ 等待500ms后重试...`)
await new Promise(resolve => setTimeout(resolve, 500))
}
}
}
/**
* 生成诊断建议
*/
function generateRecommendations(debugInfo) {
const recommendations = []
// 网络相关建议
if (debugInfo.networkInfo.type !== 'wifi') {
recommendations.push('📶 建议连接到WiFi网络移动网络无法访问局域网设备')
}
if (debugInfo.networkInfo.wifiError) {
recommendations.push('🔐 WiFi权限可能被限制请检查APP的位置权限')
}
// 请求配置建议
if (debugInfo.requestDetails.issues.length > 0) {
recommendations.push(...debugInfo.requestDetails.issues)
}
// 错误相关建议
if (debugInfo.error) {
const errorMsg = debugInfo.error.errMsg || debugInfo.error.message || ''
if (errorMsg.includes('timeout')) {
recommendations.push('⏱️ 请求超时,可能原因:')
recommendations.push(' - 目标设备未启动或不可达')
recommendations.push(' - 网络延迟过高')
recommendations.push(' - 防火墙阻止连接')
}
if (errorMsg.includes('fail')) {
recommendations.push('🚫 连接失败,可能原因:')
recommendations.push(' - 设备不在同一网络')
recommendations.push(' - IP地址错误')
recommendations.push(' - 端口被占用或关闭')
}
if (errorMsg.includes('certificate') || errorMsg.includes('ssl')) {
recommendations.push('🔒 SSL/证书问题建议使用HTTP而非HTTPS')
}
}
// Android特定建议
if (debugInfo.environment.platform === 'android') {
recommendations.push('🤖 Android特定建议')
recommendations.push(' - 确保APP有网络权限')
recommendations.push(' - 检查是否允许明文HTTP流量')
recommendations.push(' - 尝试云打包而非真机调试')
}
return recommendations
}
/**
* 打印调试报告
*/
function printDebugReport(debugInfo) {
console.log('=' * 60)
console.log('📋 HTTP调试报告')
console.log('=' * 60)
console.log('🎯 请求信息:')
console.log(` URL: ${debugInfo.url}`)
console.log(` 方法: ${debugInfo.requestDetails?.method || 'GET'}`)
console.log(` 超时: ${debugInfo.requestDetails?.timeout || 'N/A'}ms`)
console.log('\n📱 环境信息:')
if (debugInfo.environment.platform) {
console.log(` 平台: ${debugInfo.environment.platform}`)
console.log(` 设备: ${debugInfo.environment.brand} ${debugInfo.environment.model}`)
console.log(` 系统: ${debugInfo.environment.system}`)
}
console.log('\n📶 网络信息:')
console.log(` 类型: ${debugInfo.networkInfo?.type || 'unknown'}`)
console.log(` 状态: ${debugInfo.networkInfo?.isConnected ? '已连接' : '未连接'}`)
if (debugInfo.networkInfo?.wifi?.SSID) {
console.log(` WiFi: ${debugInfo.networkInfo.wifi.SSID}`)
}
console.log('\n🎯 请求结果:')
if (debugInfo.response) {
console.log(` ✅ 成功 (状态码: ${debugInfo.response.statusCode})`)
} else if (debugInfo.error) {
console.log(` ❌ 失败 (${debugInfo.error.errMsg || debugInfo.error.message})`)
}
if (debugInfo.recommendations.length > 0) {
console.log('\n💡 诊断建议:')
debugInfo.recommendations.forEach(rec => console.log(` ${rec}`))
}
console.log('=' * 60)
}
/**
* 快速测试ESP32连接
*/
export async function quickTestESP32(ip = '192.168.1.98') {
console.log(`🚀 快速测试ESP32连接: ${ip}`)
const testAPIs = [
'/api/device/info',
'/api/status',
'/api/info',
'/'
]
for (const api of testAPIs) {
const url = `http://${ip}:80${api}`
console.log(`\n🔍 测试: ${api}`)
const result = await debugHTTPRequest(url, {
method: 'GET',
timeout: 8000
})
if (result.response && result.response.statusCode === 200) {
console.log(`✅ 找到可用接口: ${api}`)
return {
success: true,
api,
ip,
response: result.response
}
}
}
console.log('❌ 所有接口测试失败')
return {
success: false,
ip
}
}
export default {
debugHTTPRequest,
quickTestESP32
}