-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhttp_client.cpp
More file actions
116 lines (89 loc) · 2.89 KB
/
Copy pathhttp_client.cpp
File metadata and controls
116 lines (89 loc) · 2.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "http_client.h"
bool HttpClient::init() {
LOGI("🌐 Initializing modem HTTP stack");
bool netOpenOk = cell.atp("AT+NETOPEN\r", 10000);
if (!netOpenOk && cell.respHas("Network is already opened")) {
netOpenOk = true;
}
bool httpTermOk = cell.atp("AT+HTTPTERM\r", 3000);
bool httpInitOk = cell.atp("AT+HTTPINIT\r", 5000);
LOGI("🌐 HTTP stack results: NETOPEN=%d HTTPTERM=%d HTTPINIT=%d",
netOpenOk ? 1 : 0,
httpTermOk ? 1 : 0,
httpInitOk ? 1 : 0);
return netOpenOk && httpInitOk;
}
void HttpClient::recover() {
LOGW("🔧 Recovering HTTP stack...");
cell.atp("AT+HTTPTERM\r", 3000);
cell.atp("AT+NETCLOSE\r", 5000);
delay(500);
init();
}
void HttpClient::httpReadAndPrint(int len) {
if (len <= 0) return;
const int cap = 800;
int toRead = (len > cap) ? cap : len;
char cmd[64];
snprintf(cmd, sizeof(cmd), "AT+HTTPREAD=0,%d\r", toRead);
cell.atp(cmd, 8000);
LOGW("---- HTTPREAD (truncated) ----");
const char* r = cell.lastResp();
if (r) Serial.println(r);
LOGW("---- END HTTPREAD ----");
}
bool HttpClient::waitHTTPACTION(int& status, int& len) {
status = -1;
len = 0;
if (!cell.waitFor("+HTTPACTION:", 45000)) return false;
const char* r = cell.lastResp();
if (!r) return false;
const char* p = strstr(r, "+HTTPACTION:");
if (!p) return false;
const char* c1 = strchr(p, ',');
if (!c1) return false;
status = atoi(c1 + 1);
const char* c2 = strchr(c1 + 1, ',');
if (!c2) return false;
len = atoi(c2 + 1);
return true;
}
bool HttpClient::postOnce(const char* payload, int payloadLen, int rowsForLog) {
char urlCmd[256];
snprintf(urlCmd, sizeof(urlCmd), "AT+HTTPPARA=\"URL\",\"%s\"\r", API_URL);
cell.atp(urlCmd);
cell.atp("AT+HTTPPARA=\"CONTENT\",\"application/json\"\r");
char hdr[160];
snprintf(hdr, sizeof(hdr), "AT+HTTPPARA=\"USERDATA\",\"X-Device-Token: %s\"\r", DEVICE_TOKEN);
cell.atp(hdr);
char dataCmd[64];
snprintf(dataCmd, sizeof(dataCmd), "AT+HTTPDATA=%d,10000\r", payloadLen);
cell.atp(dataCmd, 3000);
if (!cell.respHas("DOWNLOAD")) {
LOGE("❌ No DOWNLOAD prompt from HTTPDATA");
return false;
}
cell.atp(payload, 10000);
cell.atp("AT+HTTPACTION=1\r", 5000);
int status = -1, len = 0;
if (!waitHTTPACTION(status, len)) {
LOGE("❌ HTTPACTION timeout (no URC parsed)");
return false;
}
LOGI("[HTTP POST] Status: %d Len: %d (rows=%d)", status, len, rowsForLog);
if (status >= 400) {
httpReadAndPrint(len);
}
return (status >= 200 && status < 300);
}
bool HttpClient::postJson(const char* payload, int payloadLen, int rowsForLog) {
if (postOnce(payload, payloadLen, rowsForLog)) return true;
LOGW("⚠️ POST failed. Recovering and retrying once...");
recover();
if (!postOnce(payload, payloadLen, rowsForLog)) {
LOGE("❌ POST failed after retry.");
return false;
}
LOGI("✅ POST succeeded after recovery retry.");
return true;
}