# V0.3 调用网络API查询温湿度数据
This commit is contained in:
170
src/main.cpp
170
src/main.cpp
@ -40,9 +40,16 @@ void reconnectMQTT (); // MQTT重连函数
|
|||||||
void checkWifiConnection (); // WiFi连接检查函数
|
void checkWifiConnection (); // WiFi连接检查函数
|
||||||
void checkMqttConnection (); // MQTT连接检查函数
|
void checkMqttConnection (); // MQTT连接检查函数
|
||||||
|
|
||||||
bool parseHexJson (String jsonStr); // 解析16进制字符串并返回数据
|
// bool parseHexJson (String jsonStr); // 解析16进制字符串并返回数据
|
||||||
bool parseCompactData (const char *data); // 解析紧凑型数据并返回数据
|
bool parseCompactData (const char *data); // 解析紧凑型数据并返回数据
|
||||||
|
|
||||||
|
bool getNanchangWeather (); // 获取天气信息并解析
|
||||||
|
|
||||||
|
// 天气API配置
|
||||||
|
const char *weatherHost = "restapi.amap.com";
|
||||||
|
const String API_KEY = "95f833b07d781a2531f5e1516f466515"; // 替换为实际API密钥
|
||||||
|
const String LOCATION_ADCODE = "360113"; // 城市代码
|
||||||
|
|
||||||
// MQTT相关配置信息
|
// MQTT相关配置信息
|
||||||
const char *mqtt_broker_addr = "mqtt.lovelyqi.cn"; // 服务器地址
|
const char *mqtt_broker_addr = "mqtt.lovelyqi.cn"; // 服务器地址
|
||||||
const uint16_t mqtt_broker_port = 1883; // 服务端口号
|
const uint16_t mqtt_broker_port = 1883; // 服务端口号
|
||||||
@ -75,6 +82,8 @@ setup ()
|
|||||||
mqttClient.setServer (mqtt_broker_addr, mqtt_broker_port);
|
mqttClient.setServer (mqtt_broker_addr, mqtt_broker_port);
|
||||||
// mqttClient.setBufferSize (mqtt_client_buff_size);
|
// mqttClient.setBufferSize (mqtt_client_buff_size);
|
||||||
mqttClient.setCallback (mqtt_callback);
|
mqttClient.setCallback (mqtt_callback);
|
||||||
|
|
||||||
|
getNanchangWeather (); // 获取天气信息并解析
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -88,7 +97,8 @@ loop ()
|
|||||||
String jsonStr = Serial.readStringUntil ('\n');
|
String jsonStr = Serial.readStringUntil ('\n');
|
||||||
if (jsonStr.startsWith ("{"))
|
if (jsonStr.startsWith ("{"))
|
||||||
{
|
{
|
||||||
parseHexJson (jsonStr);
|
// parseHexJson (jsonStr);
|
||||||
|
parseCompactData (jsonStr.c_str ());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -101,7 +111,7 @@ loop ()
|
|||||||
// 维护MQTT连接
|
// 维护MQTT连接
|
||||||
checkMqttConnection ();
|
checkMqttConnection ();
|
||||||
|
|
||||||
// 3. 定时上传数据( xxx ms间隔 )
|
// 定时上传数据( xxx ms间隔 )
|
||||||
static unsigned long lastUpload = 0;
|
static unsigned long lastUpload = 0;
|
||||||
if (millis () - lastUpload > 500)
|
if (millis () - lastUpload > 500)
|
||||||
{
|
{
|
||||||
@ -110,6 +120,14 @@ loop ()
|
|||||||
lastUpload = millis ();
|
lastUpload = millis ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 定时获取温湿度信息( 5 s间隔 )
|
||||||
|
static unsigned long lastGetTemp = 0;
|
||||||
|
if (millis () - lastGetTemp > 5000)
|
||||||
|
{
|
||||||
|
getNanchangWeather ();
|
||||||
|
lastGetTemp = millis ();
|
||||||
|
}
|
||||||
|
|
||||||
// 4. 处理低功耗需求
|
// 4. 处理低功耗需求
|
||||||
#ifdef LOW_POWER_MODE
|
#ifdef LOW_POWER_MODE
|
||||||
ESP.deepSleep (30e6); // 30秒深度睡眠
|
ESP.deepSleep (30e6); // 30秒深度睡眠
|
||||||
@ -256,46 +274,46 @@ hex4ToUint (const char *p)
|
|||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
// 输入示例:{"vol":1069,"cur":0037,"pwr":00E7,"tmp":0CA2,"hum":0BF6}
|
// // 输入示例:{"vol":1069,"cur":0037,"pwr":00E7,"tmp":0CA2,"hum":0BF6}
|
||||||
bool
|
// bool
|
||||||
parseHexJson (String jsonStr)
|
// parseHexJson (String jsonStr)
|
||||||
{
|
// {
|
||||||
// 键名位置查找(基于固定结构优化)
|
// // 键名位置查找(基于固定结构优化)
|
||||||
const char *key_pos[5] = {
|
// const char *key_pos[5] = {
|
||||||
strstr (jsonStr.c_str (), "\"vol\":"), // 电压位置
|
// strstr (jsonStr.c_str (), "\"vol\":"), // 电压位置
|
||||||
strstr (jsonStr.c_str (), "\"cur\":"), // 电流位置
|
// strstr (jsonStr.c_str (), "\"cur\":"), // 电流位置
|
||||||
strstr (jsonStr.c_str (), "\"pwr\":"), // 功率位置
|
// strstr (jsonStr.c_str (), "\"pwr\":"), // 功率位置
|
||||||
strstr (jsonStr.c_str (), "\"tmp\":"), // 温度位置
|
// strstr (jsonStr.c_str (), "\"tmp\":"), // 温度位置
|
||||||
strstr (jsonStr.c_str (), "\"hum\":") // 湿度位置
|
// strstr (jsonStr.c_str (), "\"hum\":") // 湿度位置
|
||||||
};
|
// };
|
||||||
|
|
||||||
// 校验键名完整性
|
// // 校验键名完整性
|
||||||
for (uint8_t i = 0; i < 5; i++)
|
// for (uint8_t i = 0; i < 5; i++)
|
||||||
{
|
// {
|
||||||
if (!key_pos[i])
|
// if (!key_pos[i])
|
||||||
return false;
|
// return false;
|
||||||
key_pos[i] += 5; // 跳过键名部分(如"vol":)
|
// key_pos[i] += 5; // 跳过键名部分(如"vol":)
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 逐字段解析(固定4字节长度)
|
// // 逐字段解析(固定4字节长度)
|
||||||
sensorData.voltage = hex4ToUint (key_pos[0]) / 100;
|
// sensorData.voltage = hex4ToUint (key_pos[0]) / 100;
|
||||||
Serial.println (key_pos[0]);
|
// Serial.println (key_pos[0]);
|
||||||
Serial.println (hex4ToUint ("109A"));
|
// Serial.println (hex4ToUint ("109A"));
|
||||||
sensorData.current = hex4ToUint (key_pos[1]) / 100;
|
// sensorData.current = hex4ToUint (key_pos[1]) / 100;
|
||||||
sensorData.power = hex4ToUint (key_pos[2]) / 100;
|
// sensorData.power = hex4ToUint (key_pos[2]) / 100;
|
||||||
Serial.println (sensorData.power);
|
// Serial.println (sensorData.power);
|
||||||
sensorData.temp = hex4ToUint (key_pos[3]) / 100;
|
// sensorData.temp = hex4ToUint (key_pos[3]) / 100;
|
||||||
sensorData.humidity = hex4ToUint (key_pos[4]) / 100;
|
// sensorData.humidity = hex4ToUint (key_pos[4]) / 100;
|
||||||
|
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 接收端解析函数(返回解析成功状态)
|
// 接收端解析函数(返回解析成功状态)
|
||||||
bool
|
bool
|
||||||
parseCompactData (const char *data)
|
parseCompactData (const char *data)
|
||||||
{
|
{
|
||||||
// 格式验证(长度26字节:{xxxx,xxxx,xxxx,xxxx,xxxx})
|
// 格式验证(长度26字节:{xxxx,xxxx,xxxx,xxxx,xxxx})
|
||||||
if ( data[0] != '{' || data[25] != '}')
|
if (data[0] != '{' || data[25] != '}')
|
||||||
{
|
{
|
||||||
Serial.println ("Failed to parse data, invalid format.");
|
Serial.println ("Failed to parse data, invalid format.");
|
||||||
return false;
|
return false;
|
||||||
@ -333,14 +351,84 @@ parseCompactData (const char *data)
|
|||||||
sensorData.voltage = params[0] / 100.0f;
|
sensorData.voltage = params[0] / 100.0f;
|
||||||
sensorData.current = params[1] / 100.0f;
|
sensorData.current = params[1] / 100.0f;
|
||||||
sensorData.power = params[2] / 100.0f;
|
sensorData.power = params[2] / 100.0f;
|
||||||
sensorData.temp = params[3] / 100.0f;
|
// sensorData.temp = params[3] / 100.0f;
|
||||||
sensorData.humidity = params[4] / 100.0f;
|
// sensorData.humidity = params[4] / 100.0f;
|
||||||
|
|
||||||
Serial.println (sensorData.voltage);
|
// Serial.println (sensorData.voltage);
|
||||||
Serial.println (sensorData.current);
|
// Serial.println (sensorData.current);
|
||||||
Serial.println (sensorData.power);
|
// Serial.println (sensorData.power);
|
||||||
Serial.println (sensorData.temp);
|
// Serial.println (sensorData.temp);
|
||||||
Serial.println (sensorData.humidity);
|
// Serial.println (sensorData.humidity);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 封装函数:获取南昌温湿度
|
||||||
|
bool
|
||||||
|
getNanchangWeather ()
|
||||||
|
{
|
||||||
|
WiFiClient client;
|
||||||
|
const int httpPort = 80;
|
||||||
|
|
||||||
|
if (!client.connect (weatherHost, httpPort))
|
||||||
|
{
|
||||||
|
Serial.println ("Connection failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建API请求URL
|
||||||
|
String url = "/v3/weather/weatherInfo?key=" + API_KEY
|
||||||
|
+ "&city=" + LOCATION_ADCODE + "&extensions=base";
|
||||||
|
|
||||||
|
// 发送HTTP请求
|
||||||
|
client.print (String ("GET ") + url + " HTTP/1.1\r\n" + "Host: "
|
||||||
|
+ weatherHost + "\r\n" + "Connection: close\r\n\r\n");
|
||||||
|
|
||||||
|
// 等待响应
|
||||||
|
unsigned long timeout = millis ();
|
||||||
|
while (client.available () == 0)
|
||||||
|
{
|
||||||
|
if (millis () - timeout > 500)
|
||||||
|
{
|
||||||
|
client.stop ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取HTTP响应头
|
||||||
|
while (client.available ())
|
||||||
|
{
|
||||||
|
String line = client.readStringUntil ('\n');
|
||||||
|
if (line == "\r")
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// client.readStringUntil ('{');
|
||||||
|
// String src = client.readStringUntil ('}');
|
||||||
|
// Serial.println (src);
|
||||||
|
|
||||||
|
// 解析JSON数据
|
||||||
|
DynamicJsonDocument doc (1024);
|
||||||
|
DeserializationError error = deserializeJson (doc, client);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
Serial.print ("JSON解析失败: ");
|
||||||
|
Serial.println (error.c_str ());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取温湿度数据
|
||||||
|
JsonObject results_0 = doc["lives"][0];
|
||||||
|
|
||||||
|
|
||||||
|
sensorData.temp = results_0["temperature_float"];
|
||||||
|
sensorData.humidity = results_0["humidity_float"];
|
||||||
|
|
||||||
|
// Serial.print ("温度: " + String (sensorData.temp) + "°C");
|
||||||
|
// Serial.println ("湿度: " + String (sensorData.humidity) + "%");
|
||||||
|
|
||||||
|
client.stop ();
|
||||||
|
return true;
|
||||||
|
}
|
Reference in New Issue
Block a user